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
题解:
很久之前就做了另一个版本……当时乱写,结果交过来就TLE了……今天填了一下这个坑,发现要用并查集的按秩合并,秩其实就是树的高度,并的话就把秩小的并到秩大的上,这样可以保证树的高度最小,也就保证了查询时的时间复杂度。(因为不能压缩路径)。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200010;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct tree{int lc,rc,fa,dep;}tr[maxn*30];
int len=0,root[maxn];
int n,m;
void build(int l,int r)
{
int t=++len;
if(l==r) tr[t].fa=l,tr[t].dep=1;
if(l<r)
{
int mid=l+r>>1;
tr[t].lc=len+1;build(l,mid);
tr[t].rc=len+1;build(mid+1,r);
}
}
int get(int now,int l,int r,int x)
{
if(l==r) return now;
int mid=l+r>>1;
if(x<=mid) return get(tr[now].lc,l,mid,x);
else return get(tr[now].rc,mid+1,r,x);
}
int findfa(int rt,int x)
{
int t=get(rt,0,n,x);
if(tr[t].fa==x) return t;
else return findfa(rt,tr[t].fa);
}
void update(int &now,int last,int l,int r,int x,int c)
{
int t=++len;now=t;
tr[t]=tr[last];
if(l==r){tr[t].fa=c;tr[t].dep++;return;}
int mid=l+r>>1;
if(x<=mid)update(tr[t].lc,tr[last].lc,l,mid,x,c);
else update(tr[t].rc,tr[last].rc,mid+1,r,x,c);
}
void add_dep(int &now,int last,int l,int r,int x)
{
int t=++len;now=t;
tr[t]=tr[last];
if(l==r){tr[t].dep++;return;}
int mid=l+r>>1;
if(x<=mid)add_dep(tr[t].lc,tr[last].lc,l,mid,x);
else add_dep(tr[t].rc,tr[last].rc,mid+1,r,x);
}
int main()
{
int ans=0;
n=read();m=read();
build(0,n);root[0]=1;
for(int i=1;i<=m;++i)
{
root[i]=root[i-1];
int o=read(),x=read()^ans,y;
if(o==1)
{
y=read()^ans;
int fx=findfa(root[i-1],x),fy=findfa(root[i-1],y);
if(tr[fx].fa!=tr[fy].fa)
{
if(tr[fx].dep>tr[fy].dep)swap(fx,fy);
update(root[i],root[i-1],0,n,tr[fx].fa,tr[fy].fa);
if(tr[fx].dep==tr[fy].dep)add_dep(root[i],root[i],0,n,tr[fy].fa);
}
}
else if(o==2) root[i]=root[x];
else
{
y=read()^ans;
int fx=findfa(root[i-1],x),fy=findfa(root[i-1],y);
printf("%d\n",ans=(tr[fx].fa==tr[fy].fa));
}
}
}