bzoj 3673&3674: 可持久化并查集 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
题解:
首先普通并查集操作中,是靠fa这个数组维护的
所以要可持久并查集,就要可持久化fa数组,所以用到可持久化线段树维护.
注意要路径压缩
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #define RG register 8 #define il inline 9 using namespace std; 10 const int N=2000005,M=20005; 11 int gi(){ 12 int str=0;char ch=getchar(); 13 while(ch>'9' || ch<'0')ch=getchar(); 14 while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar(); 15 return str; 16 } 17 int n,m,tot=0,root[M]; 18 struct node{ 19 int ls,rs,fa; 20 }t[N]; 21 il void build(int &rt,int l,int r){ 22 rt=++tot; 23 if(l==r){ 24 t[rt].fa=l; 25 return ; 26 } 27 int mid=(l+r)>>1; 28 build(t[rt].ls,l,mid);build(t[rt].rs,mid+1,r); 29 } 30 il int query(int rt,int l,int r,int sa){ 31 if(l==r) 32 return rt; 33 int mid=(l+r)>>1; 34 if(sa>mid)return query(t[rt].rs,mid+1,r,sa); 35 else return query(t[rt].ls,l,mid,sa); 36 } 37 il void updata(int &rt,int last,int l,int r,int sa,int to){ 38 rt=++tot;t[rt]=t[last]; 39 if(l==r){ 40 t[rt].fa=to; 41 return ; 42 } 43 int mid=(l+r)>>1; 44 if(sa>mid)updata(t[rt].rs,t[last].rs,mid+1,r,sa,to); 45 else updata(t[rt].ls,t[last].ls,l,mid,sa,to); 46 } 47 il int find(int x,int i){ 48 int c=query(root[i],1,n,x); 49 if(t[c].fa==x)return x; 50 int d=find(t[c].fa,i); 51 updata(root[i],root[i],1,n,x,d); 52 return d; 53 } 54 void work() 55 { 56 int flag,x,y,fx,fy; 57 n=gi();m=gi(); 58 build(root[0],1,n); 59 for(int i=1;i<=m;i++){ 60 flag=gi();x=gi(); 61 if(flag==1){ 62 y=gi(); 63 root[i]=root[i-1]; 64 fx=find(x,i);fy=find(y,i); 65 if(fx==fy)continue; 66 updata(root[i],root[i-1],1,n,fx,fy); 67 } 68 else if(flag==2)root[i]=root[x]; 69 else{ 70 y=gi(); 71 root[i]=root[i-1]; 72 fx=find(x,i);fy=find(y,i); 73 if(fx==fy)puts("1"); 74 else puts("0"); 75 } 76 } 77 } 78 79 int main() 80 { 81 work(); 82 return 0; 83 }