【BZOJ3674】可持久化并查集加强版
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
题解:要实现可持久化并查集,只需实现可持久化数组,要实现可持久化数组,只能用可持久化线段树QAQ
具体方法是,让可持久化线段树的叶子节点储存并查集的fa,siz信息,然后每次查询,更新都在可持久化线段树上完成。回到之前的状态只需要调用之前的树根就行了。此外不用路径压缩。
bz3674:
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn=200010; struct sag { int ls,rs,siz,fa; }s[maxn*50]; int n,m,tot,now,ans; int rt[maxn<<1],to[maxn]; int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f; } void insert(int x,int &y,int l,int r,int pos,int a,int b) { if(pos>r) return ; y=++tot; if(l==r) { s[y].siz=a,s[y].fa=b; return ; } int mid=l+r>>1; if(pos<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,pos,a,b); else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,pos,a,b); } int query(int l,int r,int x,int pos) { if(l==r) return x; int mid=l+r>>1; if(pos<=mid) return query(l,mid,s[x].ls,pos); else return query(mid+1,r,s[x].rs,pos); } void build(int l,int r,int &x) { x=++tot; if(l==r) { s[x].fa=l,s[x].siz=1; return ; } int mid=l+r>>1; build(l,mid,s[x].ls),build(mid+1,r,s[x].rs); } int find(int x) { int fx; while(1) { fx=query(1,n,rt[now],x); if(s[fx].fa!=x) x=s[fx].fa; else break; } return fx; } int main() { n=rd(),m=rd(); int i,j,a,b,c,ra,rb; build(1,n,rt[0]); for(i=1;i<=m;i++) { c=rd(); if(c==1) { a=rd()^ans,b=rd()^ans; ra=find(a),rb=find(b); if(s[ra].siz>s[rb].siz) swap(ra,rb); insert(rt[now],rt[now+1],1,n,s[rb].fa,s[rb].siz+s[ra].siz,s[rb].fa),now++; insert(rt[now],rt[now+1],1,n,s[ra].fa,s[ra].siz,s[rb].fa),now++; } if(c==2) { a=rd()^ans; rt[++now]=rt[to[a]]; } if(c==3) { a=rd()^ans,b=rd()^ans; ra=find(a),rb=find(b); printf("%d ",ans=(s[ra].fa==s[rb].fa)); } to[i]=now; } return 0; }