洛谷模板c++
root[i]=root[x]; //是否是很简单呀!
#define Mid ((l+r)>>1) #define lson L[rt],l,Mid #define rson R[rt],Mid+1,r // 整个代码的三个宏定义
void build(int &rt,int l,int r) { rt=++cnt; if(l==r){fa[rt]=l;return ;} build(lson);build(rson); } // 就是普通的可持久化数组构建法,不过维护的是Fa而已
void merge(int last,int &rt,int l,int r,int pos,int Fa) { rt=++cnt;L[rt]=L[last],R[rt]=R[last]; if(l==r) { fa[rt]=Fa; dep[rt]=dep[last];//继承上个版本的值 return ; } if(pos<=Mid)merge(L[last],lson,pos,Fa); else merge(R[last],rson,pos,Fa); } // 这个就是单纯的将一个点合并到另外一个点上的可持久化数组操做!
void update(int rt,int l,int r,int pos) { if(l==r){dep[rt]++;return ;} if(pos<=Mid)update(lson,pos); else update(rson,pos); } // 可持久化数组普通操做 // 可能有人会问为何修改节点深度的时候不须要新开节点! // 其实新开节点是根据咱们的须要来的! // 若是咱们须要某个值在某个版本的信息,那么,每当这个值进行修改的时候,咱们都须要新添加一个节点,使得咱们能够查到各个版本的值 // 然而dep咱们并不须要知道它之前的值是多少,咱们只须要用它当前的值去合并就好了!
int query(int rt,int l,int r,int pos) { if(l==r)return rt; if(pos<=Mid)return query(lson,pos); else return query(rson,pos); } // 为了找祖先的操做
int find(int rt,int pos) { int now=query(rt,1,n,pos); if(fa[now]==pos)return now; return find(rt,fa[now]); } // 暴力找祖先
posx=find(root[i],x);posy=find(root[i],y); if(fa[posx]!=fa[posy]) { if(dep[posx]>dep[posy])swap(posx,posy); merge(root[i-1],root[i],1,n,fa[posx],fa[posy]); if(dep[posx]==dep[posy])update(root[i],1,n,fa[posy]); // 由于不可能出现深度相同的两个点,因此要把其中一个点深度+1,因为是深度小的合到深度大的上,因此把深度小的增长深度 }
posx=find(root[i],x);posy=find(root[i],y); if(fa[posx]==fa[posy])puts("1"); else puts("0"); // 这个真和普通并查集没区别,只是须要注意是什么版本的并查集...
其实,把上面的操做拼起来就是完整代码,不过我仍是粘一个完整版吧!git
#include<bits/stdc++.h> #define N 301000 using namespace std; template<typename T>inline void read(T &x) { x=0; static int p;p=1; static char c;c=getchar(); while(!isdigit(c)){if(c=='-')p=-1;c=getchar();} while(isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();} x*=p; } int n,m; int L[N*30],R[N*30],fa[N*30],dep[N*30]; int root[N*30]; namespace Persistant_Union_Set { #define Mid ((l+r)>>1) #define lson L[rt],l,Mid #define rson R[rt],Mid+1,r int cnt; void build(int &rt,int l,int r) { rt=++cnt; if(l==r){fa[rt]=l;return ;} build(lson);build(rson); } void merge(int last,int &rt,int l,int r,int pos,int Fa) { rt=++cnt;L[rt]=L[last],R[rt]=R[last]; if(l==r) { fa[rt]=Fa; dep[rt]=dep[last]; return ; } if(pos<=Mid)merge(L[last],lson,pos,Fa); else merge(R[last],rson,pos,Fa); } void update(int rt,int l,int r,int pos) { if(l==r){dep[rt]++;return ;} if(pos<=Mid)update(lson,pos); else update(rson,pos); } int query(int rt,int l,int r,int pos) { if(l==r)return rt; if(pos<=Mid)return query(lson,pos); else return query(rson,pos); } int find(int rt,int pos) { int now=query(rt,1,n,pos); if(fa[now]==pos)return now; return find(rt,fa[now]); } #undef Mid #undef lson #undef rson } using namespace Persistant_Union_Set; int main() { read(n);read(m); build(root[0],1,n); for(int i=1;i<=m;i++) { static int opt,x,y; read(opt);read(x); if(opt==1) { read(y); static int posx,posy; root[i]=root[i-1]; posx=find(root[i],x);posy=find(root[i],y); if(fa[posx]!=fa[posy]) { if(dep[posx]>dep[posy])swap(posx,posy); merge(root[i-1],root[i],1,n,fa[posx],fa[posy]); if(dep[posx]==dep[posy])update(root[i],1,n,fa[posy]); } } else if(opt==2)root[i]=root[x]; else if(opt==3) { read(y); root[i]=root[i-1]; static int posx,posy; posx=find(root[i],x);posy=find(root[i],y); if(fa[posx]==fa[posy])puts("1"); else puts("0"); } } return 0; }