bzoj 3673: 可持久化并查集 by zky
Description
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
0<n,m<=2*10^4
Input
Output
Sample Input
5 6
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
Sample Output
1
0
1
0
1
可持久化并查集模板题,不能路径压缩,我们要按秩合并(保证树高),用主席树记录每个节点在不同时刻的父亲。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define F(i,a,b) for(int i=a;i<=b;i++) 4 #define D(i,a,b) for(int i=a;i>=b;i--) 5 #define ms(i,a) memset(a,i,sizeof(a)) 6 #define mid (l+r)/2 7 8 int const maxn=20005; 9 int const maxm=1000005; 10 11 inline int read(){ 12 int x=0; char c=getchar(); 13 while ( c<'0' || c>'9') c=getchar(); 14 while (c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar(); 15 return x; 16 } 17 18 int root[maxn],ch[maxm][2],v[maxm],deep[maxm]; 19 int n,m,sz; 20 21 void build(int &o,int l,int r){ 22 o=++sz; 23 if(l==r) { 24 v[o]=l; return ; 25 } 26 build(ch[o][0],l,mid); 27 build(ch[o][1],mid+1,r); 28 } 29 30 int query(int o,int l,int r,int pos){ 31 if(l==r) return o; 32 if(pos<=mid) return query(ch[o][0],l,mid,pos); 33 else return query(ch[o][1],mid+1,r,pos); 34 } 35 36 void modify(int l,int r,int x,int &y,int pos,int val){ 37 y=++sz; 38 if(l==r){ 39 v[y]=val; deep[y]=deep[x]; return ; 40 } 41 ch[y][0]=ch[x][0];ch[y][1]=ch[x][1]; 42 if(pos<=mid) modify(l,mid,ch[x][0],ch[y][0],pos,val); 43 else modify(mid+1,r,ch[x][1],ch[y][1],pos,val); 44 } 45 46 void add(int o,int l,int r,int pos){ 47 if(l==r){ 48 deep[o]++; return ; 49 } 50 if(pos<=mid) add(ch[o][0],l,mid,pos); 51 else add(ch[o][1],mid+1,r,pos); 52 } 53 int find(int o,int x){ 54 int p=query(o,1,n,x); 55 if(x==v[p]) return p; 56 return find(o,v[p]); 57 } 58 int main(){ 59 n=read(); 60 m=read(); 61 build(root[0],1,n); 62 F(i,1,m){ 63 int k=read(); 64 if(k==1){ 65 root[i]=root[i-1]; 66 int a=read(),b=read(); 67 int p=find(root[i],a),q=find(root[i],b); 68 if(v[p]==v[q]) continue; 69 if(deep[p]>deep[q]) swap(p,q); 70 modify(1,n,root[i-1],root[i],v[p],v[q]); 71 if(deep[p]==deep[q]) add(root[i],1,n,v[q]); 72 } 73 if(k==2){ 74 int t=read(); root[i]=root[t]; 75 } 76 if(k==3){ 77 root[i]=root[i-1]; 78 int a=read(),b=read(); 79 int p=find(root[i],a),q=find(root[i],b); 80 if(v[p]==v[q]) puts("1"); 81 else puts("0"); 82 } 83 } 84 return 0; 85 }