可持久化并查集
更新日志
2025/07/29:开工。前言
我竟然没会可持久化并查集。
实现
可持久化平衡树维护一下父节点数组,与按秩合并的秩数组即可。
模板题
code
const int N=1e5+5,M=2e5+5;
int n,m;
struct perseg{
int cnt;
int rt[M];
int ls[N<<6],rs[N<<6],dat[N<<6];
void build(int a[],int &x,int l=1,int r=n){
if(!x)x=++cnt;
if(l==r)return dat[x]=a[l],void();
int m=l+r>>1;
build(a,ls[x],l,m);
build(a,rs[x],m+1,r);
}
void copy(int x,int y){dat[y]=dat[x],ls[y]=ls[x],rs[y]=rs[x];}
void change(int k,int v,int x,int &y,int l=1,int r=n){
copy(x,y=++cnt);
if(l==r)return dat[y]=v,void();
int m=l+r>>1;
if(k<=m)change(k,v,ls[x],ls[y],l,m);
else change(k,v,rs[x],rs[y],m+1,r);
}
int query(int k,int x,int l=1,int r=n){
if(l==r)return dat[x];
int m=l+r>>1;
if(k<=m)return query(k,ls[x],l,m);
else return query(k,rs[x],m+1,r);
}
}fa,rk;
int v;
int find(int x){int f;while((f=fa.query(x,fa.rt[v]))!=x)x=f;return x;}
void merge(int a,int b){
a=find(a),b=find(b);
int rka=rk.query(a,rk.rt[v]),rkb=rk.query(b,rk.rt[v]);
if(rka>rkb)swap(a,b),swap(rka,rkb);
fa.change(a,b,fa.rt[v],fa.rt[v+1]);
if(rka==rkb)rk.change(b,rkb+1,rk.rt[v],rk.rt[v+1]);
else rk.rt[v+1]=rk.rt[v];
++v;
}
bool same(int a,int b){return find(a)==find(b);}
int Fa[N],Rk[N];
inline void Main(){
read(n,m);
rep(i,1,n)Fa[i]=i,Rk[i]=1;
fa.build(Fa,fa.rt[0]);
rk.build(Rk,rk.rt[0]);
rep(i,1,m){
int op;read(op);
if(op==1){
int a,b;read(a,b);
merge(a,b);
}else if(op==2){
int k;read(k);
++v;
fa.rt[v]=fa.rt[k];
rk.rt[v]=rk.rt[k];
}else{
int a,b;read(a,b);
put(same(a,b));
++v;
fa.rt[v]=fa.rt[v-1];
rk.rt[v]=rk.rt[v-1];
}
}
}

浙公网安备 33010602011771号