传送门:www.lydsy.com/JudgeOnline/problem.php?id=3674
可持久化并查集其实就写一个可持久化数组就可以了
可持久化数组可以用可持久化线段树或可持久化平衡树……
蒟蒻懒,用了rope:
#include<bits/stdc++.h> #include<ext/rope> using namespace std; using namespace __gnu_cxx; const int maxn=2e5+10; rope<int> *fa[maxn]; rope<int>::iterator it; int n,m; int find(int i,int x){ if(fa[i]->at(x)!=x){ int f=find(i,fa[i]->at(x)); if(f==fa[i]->at(x))return f; fa[i]->replace(x,f); return fa[i]->at(x); } return x; } void Union(int i,int x,int y){ int fx=find(i,x),fy=find(i,y); fa[i]->replace(fy,fx); } int a[maxn]; int lastans=0; int main(){ scanf("%d%d",&n,&m); for(int i=0;i<=n;i++)a[i]=i; fa[0]=new rope<int>(a,a+n+1); for(int i=1;i<=m;i++){ fa[i]=new rope<int>(*fa[i-1]); int op;scanf("%d",&op); if(op==1){ int a,b;scanf("%d%d",&a,&b); Union(i,a^lastans,b^lastans); }else if(op==2){ int k;scanf("%d",&k); fa[i]=fa[k^lastans]; }else if(op==3){ int a,b;scanf("%d%d",&a,&b); printf("%d\n",(lastans=find(i,a^lastans)==find(i,b^lastans))); } } return 0; }
献上hzwer神犇的代码
#include<cstdio> #include<iostream> using namespace std; inline int read() { int x=0;char ch=getchar(); while(ch>'9'||ch<'0')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } int n,m,sz; int root[200005],ls[2000005],rs[2000005],v[2000005],deep[2000005]; void build(int &k,int l,int r) { if(!k)k=++sz; if(l==r){v[k]=l;return;} int mid=(l+r)>>1; build(ls[k],l,mid); build(rs[k],mid+1,r); } void modify(int l,int r,int x,int &y,int pos,int val) { y=++sz; if(l==r){v[y]=val;return;} ls[y]=ls[x];rs[y]=rs[x]; int mid=(l+r)>>1; if(pos<=mid) modify(l,mid,ls[x],ls[y],pos,val); else modify(mid+1,r,rs[x],rs[y],pos,val); } int query(int k,int l,int r,int pos) { if(l==r)return k; int mid=(l+r)>>1; if(pos<=mid)return query(ls[k],l,mid,pos); else return query(rs[k],mid+1,r,pos); } void add(int k,int l,int r,int pos) { if(l==r){deep[k]++;return;} int mid=(l+r)>>1; if(pos<=mid)add(ls[k],l,mid,pos); else add(rs[k],mid+1,r,pos); } int find(int k,int x) { int p=query(k,1,n,x); if(x==v[p])return p; return find(k,v[p]); } int la=0; int main() { n=read();m=read(); build(root[0],1,n); int f,k,a,b; for(int i=1;i<=m;i++) { f=read(); if(f==1) { root[i]=root[i-1]; a=read()^la;b=read()^la; int p=find(root[i],a),q=find(root[i],b); if(v[p]==v[q])continue; if(deep[p]>deep[q])swap(p,q); modify(1,n,root[i-1],root[i],v[p],v[q]); if(deep[p]==deep[q])add(root[i],1,n,v[q]); } if(f==2) {k=read()^la;root[i]=root[k];} if(f==3) { root[i]=root[i-1]; a=read()^la;b=read()^la; int p=find(root[i],a),q=find(root[i],b); if(v[p]==v[q])puts("1"),la=1; else puts("0"),la=0; } } return 0; }
P.S. 这份代码不能A,为什么?因为我卡了哈哈O(∩_∩)O~
(其实是因为没有路径压缩……)
55555 数组开大了就能过233……