BZOJ - 3674
考虑用可持久化线段树维护
fa
和
deep
数组。并且按秩合并。
这样复杂度就是
O(nlog2n)
了。
代码里没对 deep 数组持久化。。。不过好像没什么影响。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int fa[N*25],ls[N*25],rs[N*25],tot,d[N*25],n,root[N];
void build(int &rt,int l,int r)
{
rt=++tot;
if(l==r)
{
d[rt]=1;
fa[rt]=l;
return ;
}
int m=(l+r)>>1;
build(ls[rt],l,m);
build(rs[rt],m+1,r);
}
void update(int &rt,int last,int l,int r,int x,int y)
{
rt=++tot;
ls[rt]=ls[last];
rs[rt]=rs[last];
if(l==r)
{
fa[rt]=y;
return ;
}
int m=(l+r)>>1;
if(x<=m) update(ls[rt],ls[last],l,m,x,y);
else update(rs[rt],rs[last],m+1,r,x,y);
}
void add(int rt,int l,int r,int y)
{
if(l==r)
{
++d[y];
return ;
}
int m=(l+r)>>1;
if(y<=m) add(ls[rt],l,m,y);
else add(rs[rt],m+1,r,y);
}
int query(int rt,int l,int r,int v)
{
if(l==r) return rt;
int m=(l+r)>>1;
if(v<=m) return query(ls[rt],l,m,v);
else return query(rs[rt],m+1,r,v);
}
int f(int x,int rt)
{
int p=query(rt,1,n,x);
if(x==fa[p]) return p;
else return f(fa[p],rt);
}
int main()
{
int m,ans=0;
scanf("%d%d",&n,&m);
build(root[0],1,n);
for(int i=1;i<=m;++i)
{
int op,x,y,k;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
x=x^ans;y=y^ans;
x=f(x,root[i-1]);y=f(y,root[i-1]);
if(fa[x]==fa[y]) continue;
if(d[x]>d[y]) swap(x,y);
update(root[i],root[i-1],1,n,fa[x],fa[y]);
if(d[x]==d[y]) add(root[i],1,n,fa[y]);
}
else if(op==2)
{
scanf("%d",&k);
k=k^ans;
root[i]=root[k];
}
else
{
scanf("%d%d",&x,&y);
x^=ans;y^=ans;
x=f(x,root[i-1]);y=f(y,root[i-1]);
root[i]=root[i-1];
printf("%d\n",ans=(fa[x]==fa[y]));
}
}
return 0;
}