bzoj 3674: 可持久化并查集加强版
Description
Description:
自从zkysb出了可持久化并查集后……
hzwer:乱写能AC,暴力踩标程
KuribohG:我不路径压缩就过了!
ndsf:暴力就可以轻松虐!
zky:……
n个集合 m个操作
操作:
1 a b 合并a,b所在集合
2 k 回到第k次操作之后的状态(查询算作操作)
3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
请注意本题采用强制在线,所给的a,b,k均经过加密,加密方法为x = x xor lastans,lastans的初始值为0
0<n,m<=2*10^5
Input
Output
Sample Input
5 6
1 1 2
3 1 2
2 1
3 0 3
2 1
3 1 2
1 1 2
3 1 2
2 1
3 0 3
2 1
3 1 2
Sample Output
1
0
1
0
1
类似3673。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 using namespace std; 6 int son[4000010][2],par[4000010],cnt; 7 void build(int &x,int l,int r) 8 { 9 x=++cnt; 10 if(l==r) 11 { 12 par[x]=l; 13 return; 14 } 15 int mid=(l+r)>>1; 16 build(son[x][0],l,mid); 17 build(son[x][1],mid+1,r); 18 } 19 void update(int &x,int l,int r,int p,int v) 20 { 21 cnt++; 22 son[cnt][0]=son[x][0]; 23 son[cnt][1]=son[x][1]; 24 x=cnt; 25 if(l==r) 26 { 27 par[x]=v; 28 return; 29 } 30 int mid=(l+r)>>1; 31 if(p<=mid)update(son[x][0],l,mid,p,v); 32 else update(son[x][1],mid+1,r,p,v); 33 } 34 int getpar(int x,int l,int r,int p) 35 { 36 if(l==r)return par[x]; 37 int mid=(l+r)>>1; 38 if(p<=mid)return getpar(son[x][0],l,mid,p); 39 else return getpar(son[x][1],mid+1,r,p); 40 } 41 int root[200010]; 42 int n,m; 43 pair<int,int> getrot(int k,int x) 44 { 45 int y; 46 int rnk=0; 47 while((y=getpar(root[k],1,n,x))!=x)rnk++,x=y; 48 return make_pair(x,rnk); 49 } 50 int ans; 51 int main() 52 { 53 scanf("%d%d",&n,&m); 54 build(root[0],1,n); 55 for(int i=1;i<=m;i++) 56 { 57 int op; 58 scanf("%d",&op); 59 if(op==2) 60 { 61 int k; 62 scanf("%d",&k); 63 k^=ans; 64 root[i]=root[k]; 65 } 66 else 67 { 68 root[i]=root[i-1]; 69 int a,b; 70 scanf("%d%d",&a,&b); 71 a^=ans;b^=ans; 72 pair<int,int>ta=getrot(i-1,a),tb=getrot(i-1,b); 73 a=ta.first;b=tb.first; 74 if(op==1) 75 { 76 int ra=ta.second,rb=tb.second; 77 if(a!=b) 78 { 79 if(ra<rb)update(root[i],1,n,a,b); 80 else update(root[i],1,n,b,a); 81 } 82 } 83 else 84 { 85 if(a==b)ans=1;else ans=0; 86 printf("%d\n",ans); 87 } 88 } 89 } 90 return 0; 91 }