您的位置:首页 > 其它

3674: 可持久化并查集加强版

2016-10-28 13:32 274 查看

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

因为并查集的本质就是维护一个数组,因此我们直接用可持久化线段树来维护这个数组即可。

据说是因为上一题被暴力弄过去了,所以才有了这一题。把数据范围加大,又弄成了强制在线

#include<cstdio>
using namespace std;
struct tree
{
int ll,rr;
int s;
}tr[10000001]; //40*maxn
int tot,p,la,n;
int rt[400001];
inline void build(int l,int r)//root[0]=tot=1
{
int p=tot;
if(l!=r)
{
int mid=(l+r)/2;
tot++; tr[p].ll=tot;
build(l,mid);
tot++; tr[p].rr=tot;
build(mid+1,r);
tr[p].s=tr[tr[p].ll].s+tr[tr[p].rr].s;
}
else
tr[p].s=l;
}
inline int change(int p,int ll,int rr,int l,int r,int x)//root[i]=tot+1 p=root[i-1]
{
if(p==0) return 0;
if(ll==l&&rr==r)
{
tot++;
tr[tot].s=x;
return tot;
}
else
{
int mid=(ll+rr)/2;
tot++;
int pp=tot;
if(l<=mid)
tr[pp].ll=change(tr[p].ll,ll,mid,l,r,x);
else
tr[pp].ll=tr[p].ll;
if(r>mid)
tr[pp].rr=change(tr[p].rr,mid+1,rr,l,r,x);
else
tr[pp].rr=tr[p].rr;
tr[pp].s=tr[tr[pp].ll].s+tr[tr[pp].rr].s;
return pp;
}
}
inline int ask(int p,int ll,int rr,int l,int r)
{
if(p==0) return 0;
if(ll==l&&rr==r)
return tr[p].s;
else
{
int mid=(ll+rr)/2;
if(l<=mid)
return ask(tr[p].ll,ll,mid,l,r);
if(r>mid)
return ask(tr[p].rr,mid+1,rr,l,r);
}
}
inline int find(int x)
{
if(ask(la,1,n,x,x)!=x)
{
int y=find(ask(la,1,n,x,x));
rt[p]=tot+1;
change(la,1,n,x,x,y);
la=rt[p];
}
return ask(la,1,n,x,x);
}
int main()
{
int m;
scanf("%d%d",&n,&m);
int i;
rt[0]=1;
tot=1;
build(1,n);
p=0;
la=1;
int x,s,t;
int ans=0;
for(i=1;i<=m;i++)
{
p++;
scanf("%d",&x);
if(x==1)
{
scanf("%d%d",&s,&t);
s=(s^ans);
t=(t^ans);
int fx=find(s),fy=find(t);
if(fx!=fy)
{
rt[p]=tot+1;
change(la,1,n,fx,fx,fy);
la=rt[p];
}
}
else if(x==2)
{
scanf("%d",&x);
x=(x^ans);
//p=x;
la=rt[x];
rt[p]=rt[x];
}
else if(x==3)
{
scanf("%d%d",&s,&t);
s=(s^ans);
t=(t^ans);
int fx=find(s),fy=find(t);
if(fx==fy)
{
ans=1;
printf("1\n");
}
else
{
ans=0;
printf("0\n");
}
rt[p]=rt[p-1];
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  主席树