【BZOJ3673/3674】可持久化并查集/可持久化并查集加强版 可持久化线段树

【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

Sample Output

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;
}
原文地址:https://www.cnblogs.com/CQzhangyu/p/6895073.html