用主席树实现可持久化树组(好高端的一个名字)。。
其实就是非常简单的东西,传统的可以对每一次操作都建立一个fa数组实现可持久化,但是这样会TLE+MLE,然后我们发现每次操作只会对于上一次改变很少的一部分,大部分可以沿用上一次操作的数组,这就出现了我们的黑科技——主席树,用它来实现,用它来维护每一个点的 fa ,初始时建树 fa[i]=i ,然后不断更新就可以了。
对于3673据说不用路径压缩会更快。
对于3674不用路径压缩会T到死……
还有我写了随机合并
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
int sc()
{
int i=0; char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i;
}
int fa[8000005],ch[8000005][2];
int root[22222],n,m,cnt;
void build(int &x,int l,int r)
{
if(!x)x=++cnt;
if(l==r)
{
fa[x]=l;
return ;
}
int mid=l+r>>1;
build(ch[x][0],l,mid);
build(ch[x][1],mid+1,r);
}
void change(int pre,int &x,int l,int r,int v,int f)
{
if(!x)x=++cnt;
if(l==r)
{
fa[x]=f;
return ;
}
int mid=l+r>>1;
if(v>mid)
ch[x][0]=ch[pre][0],
change(ch[pre][1],ch[x][1],mid+1,r,v,f);
else
ch[x][1]=ch[pre][1],
change(ch[pre][0],ch[x][0],l,mid,v,f);
}
int ask(int x,int l,int r,int v)
{
if(l==r)return fa[x];
int mid=l+r>>1;
if(v>mid) return ask(ch[x][1],mid+1,r,v);
else return ask(ch[x][0],l,mid,v);
}
int find(int x,int k)
{
int f=ask(root[k],1,n,x);
while(f!=x)
{
x=f;
f=ask(root[k],1,n,x);
}
return f;
}
void Union(int x,int y,int k)
{
int fx=find(x,k);
int fy=find(y,k);
change(root[k],root[k+1],1,n,fx,fy);
}
int main()
{
n=sc();m=sc();
build(root[0],1,n);
for(int i=1;i<=m;i++)
{
int opt=sc();
if(opt==1)
{
int x=sc(),y=sc();
if(rand()%2)swap(x,y);
Union(x,y,i-1);
}
else if(opt==2)
root[i]=root[sc()];
else
{
int x=sc(),y=sc();
int fx=find(x,i-1);
int fy=find(y,i-1);
if(fx==fy)puts("1");
else puts("0");
root[i]=root[i-1];
}
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
int sc()
{
int i=0; char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i;
}
int fa[16000005],ch[16000005][2];
int root[222222],n,m,cnt,ans;
void build(int &x,int l,int r)
{
if(!x)x=++cnt;
if(l==r)
{
fa[x]=l;
return ;
}
int mid=l+r>>1;
build(ch[x][0],l,mid);
build(ch[x][1],mid+1,r);
}
void change(int pre,int &x,int l,int r,int v,int f)
{
if(!x)x=++cnt;
if(l==r)
{
fa[x]=f;
return ;
}
int mid=l+r>>1;
if(v>mid)
ch[x][0]=ch[pre][0],
change(ch[pre][1],ch[x][1],mid+1,r,v,f);
else
ch[x][1]=ch[pre][1],
change(ch[pre][0],ch[x][0],l,mid,v,f);
}
int ask(int x,int l,int r,int v)
{
if(l==r)return fa[x];
int mid=l+r>>1;
if(v>mid) return ask(ch[x][1],mid+1,r,v);
else return ask(ch[x][0],l,mid,v);
}
int find(int x,int k)
{
int fa=ask(root[k],1,n,x);
if(fa==x)return fa;
fa=find(fa,k);
int u=root[k]; root[k]=0;
change(u,root[k],1,n,x,fa);
return fa;
}
void Union(int x,int y,int k)
{
int fx=find(x,k);
int fy=find(y,k);
int u=root[k]; root[k]=0;
change(u,root[k],1,n,fx,fy);
}
int main()
{
n=sc();m=sc();
build(root[0],1,n);
for(int i=1;i<=m;i++)
{
int opt=sc();
if(opt==1)
{
int x=sc()^ans,y=sc()^ans;
if(rand()%2)swap(x,y);
root[i]=root[i-1];
Union(x,y,i);
}
else if(opt==2)
root[i]=root[sc()^ans];
else
{
int x=sc()^ans,y=sc()^ans;
root[i]=root[i-1];
int fx=find(x,i);
int fy=find(y,i);
printf("%d\n",ans=(fx==fy));
}
}
return 0;
}