【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树

没什么好说的。

可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲。

Q:不是很清楚空间开多大,每次询问父亲操作后修改的节点个数是不确定的。。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define N 20005
 4 using namespace std;
 5 inline int read(){
 6   int x=0,f=1;char ch=getchar();
 7   while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8   while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 9   return x*f;
10 }
11 int n,m,rt[N],tot;
12 int f[N*100],ls[N*100],rs[N*100];
13 void build(int &x,int l,int r){
14   x=++tot;
15   if(l==r){f[x]=l;return;}
16   int mid=l+r>>1;
17   build(ls[x],l,mid);
18   build(rs[x],mid+1,r);
19 }
20 int find(int x,int l,int r,int pos){
21   if(l==r)return f[x];
22   int mid=l+r>>1;
23   if(pos<=mid)return find(ls[x],l,mid,pos);
24   else return find(rs[x],mid+1,r,pos); 
25 }
26 void update(int pre,int &x,int l,int r,int pos,int val){
27   x=++tot;ls[x]=ls[pre];rs[x]=rs[pre]; 
28   if(l==r){f[x]=val;return;}
29   int mid=l+r>>1;
30   if(pos<=mid)update(ls[pre],ls[x],l,mid,pos,val);
31   else update(rs[pre],rs[x],mid+1,r,pos,val);
32 }
33 int findfa(int ti,int x){
34   int tmp=find(rt[ti],1,n,x);
35   if(tmp==x)return x;
36   else{
37     tmp=findfa(ti,tmp);
38     update(rt[ti],rt[ti],1,n,x,tmp);
39     return tmp;
40   }
41 }
42 void unite(int ti,int x,int y){
43   int fx=findfa(ti,x),fy=findfa(ti,y);
44   if(fx<fy)swap(x,y),swap(fx,fy);
45   if(fx!=fy)update(rt[ti],rt[ti],1,n,fx,fy);
46 }
47 int main(){
48   n=read();m=read();
49   build(rt[0],1,n);
50   for(int i=1;i<=m;i++){
51     rt[i]=rt[i-1];
52     int t=read();
53     if(t==1){
54       int x=read(),y=read();
55       unite(i,x,y);
56     }
57     else if(t==2){
58       int k=read();rt[i]=rt[k];
59     }
60     else{
61       int x=read(),y=read();
62       findfa(i,x)==findfa(i,y)?puts("1"):puts("0");
63     }
64   }
65   return 0;
66 }
View Code

3673: 可持久化并查集 by zky

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 1506  Solved: 677
[Submit][Status][Discuss]

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
原文地址:https://www.cnblogs.com/wjyi/p/5568632.html