没什么好说的。
可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲。
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 }
3673: 可持久化并查集 by zky
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 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
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2
Sample Output
1
0
1
0
1