洛谷模板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; }