可持久化并查集[BZOJ3673]
#include<bits/stdc++.h>
using namespace std;
const int N=2000005;
int n,m,a,b,op,tot,root[N],lc[N],rc[N],deep[N],fa[N];
int read(){
int num=0;char ch=getchar();
while(isdigit(ch)==0)ch=getchar();
while(isdigit(ch)!=0){num=num*10+ch-'0';ch=getchar();}
return num;
}
void build(int &o,int L,int R){
if(!o)o=++tot;
if(L==R){fa[o]=L;return;}
int M=L+R>>1;
build(lc[o],L,M);
build(rc[o],M+1,R);
}
void modify(int &o,int L,int R,int last,int pos,int val){
o=++tot;
if(L==R){fa[o]=val,deep[o]=deep[last];return;}
lc[o]=lc[last],rc[o]=rc[last];
int M=L+R>>1;
if(pos<=M)modify(lc[o],L,M,lc[last],pos,val);
else modify(rc[o],M+1,R,rc[last],pos,val);
}
int query(int o,int L,int R,int pos){
if(L==R)return o;
int M=L+R>>1;
if(pos<=M)return query(lc[o],L,M,pos);
else return query(rc[o],M+1,R,pos);
}
void add(int o,int L,int R,int pos){
if(L==R){deep[o]++;return;}
int M=L+R>>1;
if(pos<=M)add(lc[o],L,M,pos);
else add(rc[o],M+1,R,pos);
}
int find(int root,int x){
int p=query(root,1,n,x);
if(x==fa[p])return p;
return find(root,fa[p]);
}
int main()
{
n=read(),m=read();
build(root[0],1,n);
for(int i=1;i<=m;i++){
op=read();
if(op==1){
root[i]=root[i-1];
a=read(),b=read();
int p=find(root[i],a),q=find(root[i],b);
if(fa[p]==fa[q])continue;
if(deep[p]>deep[q])swap(p,q);
modify(root[i],1,n,root[i-1],fa[p],fa[q]);
if(deep[p]==deep[q])add(root[i],1,n,fa[q]);
}else if(op==2){
a=read();root[i]=root[a];
}else{
root[i]=root[i-1];
a=read(),b=read();
int p=find(root[i],a),q=find(root[i],b);
if(fa[p]^fa[q])puts("0");
else puts("1");
}
}return 0;
}
树套树[BZOJ3196]
//BIT套动态开点权值线段树
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;
const int N=5e4+10;
const int inf=1e8;
int ch[N*200][2],v[N*200],root[N],num[N],tmp1[N],tmp2[N],tot=0,x,a,b,c,d,n,m;
inline int lowbit(int x){return x&-x;}
void add(int &o,int L,int R,int x,int p){
if(!o)o=++tot;
if(L==R)v[o]+=p;
else{
int M=L+R>>1;
if(x<=M)add(ch[o][0],L,M,x,p);
else add(ch[o][1],M+1,R,x,p);
v[o]=v[ch[o][0]]+v[ch[o][1]];
}
}
void change(int x,int p){
int tmp=num[x];
for(;x<=N;x+=lowbit(x)){
if(tmp!=-1)add(root[x],0,inf,tmp,-1);
add(root[x],0,inf,p,1);
}
}
bool pushdown(int L,int R,int k){
bool ans=0;
for(;R;R-=lowbit(R))tmp1[R]=ch[tmp1[R]][k],ans|=tmp1[R];
for(;L;L-=lowbit(L))tmp2[L]=ch[tmp2[L]][k],ans|=tmp2[L];
return ans;
}
void reset(int L,int R){
for(int i=R;i;i-=lowbit(i))tmp1[i]=root[i];
for(int i=L;i;i-=lowbit(i))tmp2[i]=root[i];
}
int query1(int L,int R,int ql,int qr,int k){
if(k<0||L==R)return 1;
int M=L+R>>1;
if(k<=M){
if(!pushdown(ql,qr,0))return 1;
return query1(L,M,ql,qr,k);
}else{
int w=0;
for(int i=qr;i;i-=lowbit(i))w+=v[ch[tmp1[i]][0]];
for(int i=ql;i;i-=lowbit(i))w-=v[ch[tmp2[i]][0]];
if(!pushdown(ql,qr,1))return w+1;
return w+query1(M+1,R,ql,qr,k);
}
}
int query2(int L,int R,int ql,int qr,int k){
if(k<=0)return -1;
int w=0;
for(int i=qr;i;i-=lowbit(i))w+=v[tmp1[i]];
for(int i=ql;i;i-=lowbit(i))w-=v[tmp2[i]];
if(w<k)return -1;
if(L==R)return L;
int M=L+R>>1;w=0;
for(int i=qr;i;i-=lowbit(i))w+=v[ch[tmp1[i]][0]];
for(int i=ql;i;i-=lowbit(i))w-=v[ch[tmp2[i]][0]];
if(k<=w){
pushdown(ql,qr,0);
return query2(L,M,ql,qr,k);
}else{
pushdown(ql,qr,1);
return query2(M+1,R,ql,qr,k-w);
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(num,-1,sizeof(num));
rep(i,1,n){scanf("%d",&x);change(i,x);num[i]=x;}
while(m--){
scanf("%d%d%d",&a,&b,&c);
if(a==3){change(b,c);num[b]=c;}
else{
scanf("%d",&d);
if(a==1){
reset(b-1,c);
printf("%d\n",query1(0,inf,b-1,c,d));
}
if(a==2){
reset(b-1,c);
printf("%d\n",query2(0,inf,b-1,c,d));
}
if(a==4){
reset(b-1,c);
int rk=query1(0,inf,b-1,c,d);
reset(b-1,c);
if(rk==1) printf("fuck\n");
else printf("%d\n",query2(0,inf,b-1,c,rk-1));
}
if(a==5){
reset(b-1,c);
int rk=query1(0,inf,b-1,c,d+1);
reset(b-1,c);
int re=query2(0,inf,b-1,c,rk);
if(re==-1) printf("fuck\n");
else printf("%d\n",re);
}
}
}return 0;
}
少女填坑中...