https://www.luogu.org/problemnew/show/P3402
题意很简单。
这道题,看见题目就知道应该是可持久化数据结构。而且题目还说了上一个版本的的情况。所以肯定就是主席树有关。
既然是可持久化并查集,那么就应该等于 可持久化数组+并查集。
我最开始弄了一个什么压缩的路径的可持久化数组+并查集,结果错得不知所措,只能过样例。。。现在还是不知道怎么错了。
结果就到处乱想,还差点想到了LCT上去.到现在都不知道能不能用路径压缩的并查集写。
然后看了有人用不带路径的并查集过了,然后就想了想,是挺好写的,看着是挺浪费内存的,但不过管他的。写了几发,错了几发
然后T了一发,情况就是并查集退化为一条链,很费时间,最后看见大佬用的均摊树的深度。然后写了一下,发现确实是这样的。
具体步骤如下:
在主席树上,查询某一个版本中一个点的父亲,然后跳到它的父亲,重复上面的步骤直到找到root。
关于深度的均摊,这方面吧深度小的往深度大上面并,同时深度小的并上后深度加1,这样是可以过的。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
const int M=20;
typedef long long ll;
typedef unsigned long long ull;
int root[N],lson[N*20],rson[N*20];
int tot=0,n,m,fa[N*20],deep[N*20];
int build(int l,int r)
{
int now=++tot;
if(l==r){
fa[now]=l;
return now;
}
int mid=(l+r)>>1;
lson[now]=build(l,mid);
rson[now]=build(mid+1,r);
return now;
}
int update(int last,int l,int r,int pos,int ff)
{
int now=++tot;
rson[now]=rson[last],fa[now]=fa[last];
lson[now]=lson[last],deep[now]=deep[last];
if(l==r){
fa[now]=ff;
return now;
}
int mid=(l+r)>>1;
if(pos<=mid) lson[now]=update(lson[last],l,mid,pos,ff);
else rson[now]=update(rson[last],mid+1,r,pos,ff);
return now;
}
int query(int ed,int l,int r,int pos)
{
if(l==r) return ed;
int mid=(l+r)>>1;
if(pos<=mid) return query(lson[ed],l,mid,pos);
else return query(rson[ed],mid+1,r,pos);
}
void add(int rt,int l,int r,int pos)
{
if(l==r){
deep[rt]++;
return;
}
int mid=(l+r)>>1;
if(pos<=mid) add(lson[rt],l,mid,pos);
else add(rson[rt],mid+1,r,pos);
}
int ffind(int ed,int x)
{
int fx=query(ed,1,n,x);
if(x==fa[fx]) return fx;
return ffind(ed,fa[fx]);
}
int main()
{
int op,x,y;
scanf("%d%d",&n,&m);
root[0]=build(1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1){
root[i]=root[i-1];
scanf("%d%d",&x,&y);
int fx=ffind(root[i-1],x);
int fy=ffind(root[i-1],y);
if(fa[fx]==fa[fy]) continue;
if(deep[fx]>deep[fy]) swap(fx,fy);
root[i]=update(root[i-1],1,n,fa[fx],fa[fy]);
add(root[i],1,n,fa[fy]);
}
if(op==2){
scanf("%d",&x);
root[i]=root[x];
}
if(op==3){
root[i]=root[i-1];
scanf("%d%d",&x,&y);
int fx=ffind(root[i-1],x);
int fy=ffind(root[i-1],y);
if(fa[fx]==fa[fy]) puts("1");
else puts("0");
}
}
return 0;
}