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

Sample Output

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 }
View Code

 

posted @ 2019-09-03 20:02  zjxxcn  阅读(112)  评论(0编辑  收藏  举报