您的位置:首页 > 其它

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

2017-05-23 17:24 344 查看

【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\n",ans=(s[ra].fa==s[rb].fa));
}
to[i]=now;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐