【BZOJ3674】—可持久化并查集加强版(可持久化并查集)

传送门

我还以为可持久化并查集是什么呢

可持久化并查集==可持久化++并查集==主席树++并查集

考虑到每次状态只会修改一个集合

于是就想可持久化数组一样

维护一颗主席树来维护每个点的fafa

#include<bits/stdc++.h>
using namespace std;
#define gc getchar
#define ll long long
inline int read(){
	char ch=gc();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=gc();}
	while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch^48),ch=gc();}
	return res*f;
}
#undef gc
const int N=200005;
const int Log=30;
int lc[N*Log],rc[N*Log],fa[N*Log],dep[N*Log],n,m,tot,rt[N*Log];
#define mid ((l+r)>>1)
void buildtree(int &u,int l,int r){
	u=++tot;
	if(l==r){fa[u]=l;return;}
	buildtree(lc[u],l,mid),buildtree(rc[u],mid+1,r);
}
void merge(int pre,int &u,int l,int r,int pos,int f){
	u=++tot,lc[u]=lc[pre],rc[u]=rc[pre];
	if(l==r){
		fa[u]=f,dep[u]=dep[pre];return;
	}
	if(pos<=mid)merge(lc[pre],lc[u],l,mid,pos,f);
	else merge(rc[pre],rc[u],mid+1,r,pos,f);
}
void update(int u,int l,int r,int pos){
	if(l==r){dep[u]++;return;}
	if(pos<=mid)update(lc[u],l,mid,pos);
	else update(rc[u],mid+1,r,pos);
}
int query(int u,int l,int r,int pos){
	if(l==r)return u;
	if(pos<=mid)return query(lc[u],l,mid,pos);
	else return query(rc[u],mid+1,r,pos);
}
int find(int u,int pos){
	int now=query(u,1,n,pos);
	if(fa[now]==pos)return now;
	return find(u,fa[now]);
}
int main(){
	n=read(),m=read();
	buildtree(rt[0],1,n);
	for(int i=1;i<=m;i++){
		int op=read(),x=read();
		if(op==1){
			rt[i]=rt[i-1];
			int y=read();
			int f1=find(rt[i],x),f2=find(rt[i],y);
			if(fa[f1]!=fa[f2]){
				if(dep[f1]>dep[f2])swap(f1,f2);
				merge(rt[i-1],rt[i],1,n,fa[f1],fa[f2]);
				if(dep[f1]==dep[f2])update(rt[i],1,n,fa[f2]);
			}
		}
		else if(op==2)rt[i]=rt[x];
		else if(op==3){
			int y=read();
			rt[i]=rt[i-1];
			int f1=find(rt[i],x),f2=find(rt[i],y);
			if(fa[f1]==fa[f2])puts("1");
			else puts("0");
		}
	}
}
posted @ 2019-01-22 11:15  Stargazer_cykoi  阅读(103)  评论(0编辑  收藏  举报