# 【2019.8.20 NOIP模拟赛 T3】小X的图（history）（可持久化并查集）

### 代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 300000
#define LN 20
#define swap(x,y) (x^=y^=x^=y)
using namespace std;
int n;
class FastIO
{
private:
#define FS 100000
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Tp I void readc(Ty& x) {W(isspace(x=tc()));}
}F;
class PersistentUnionFindSet//可持久化并查集
{
private:
#define LT l,mid,O[rt].S[0]
#define RT mid+1,r,O[rt].S[1]
int n,Nt,Rt[N+5];struct node {int f,g,S[2];}O[N*LN<<1];
I int getfa(CI rt,CI x) {RI t=Qry(x,1,n,rt);return O[t].f^x?getfa(rt,O[t].f):t;}//找祖先
I void Build(CI l,CI r,int& rt)//建树
{
if(rt=++Nt,l==r) return (void)(O[rt].f=l);RI mid=l+r>>1;
Build(LT),Build(RT);
}
I int Qry(CI x,CI l,CI r,CI rt)//询问
{
if(!rt) return 0;if(l==r) return rt;RI mid=l+r>>1;
return x<=mid?Qry(x,LT):Qry(x,RT);
}
I void Upt(CI x,CI f,CI l,CI r,int& rt)//修改父亲
{
if(O[++Nt]=O[rt],rt=Nt,l==r) return (void)(O[rt].f=f);RI mid=l+r>>1;
x<=mid?Upt(x,f,LT):Upt(x,f,RT);
}
I void Add(CI x,CI l,CI r,int& rt)//将深度加1
{
if(O[++Nt]=O[rt],rt=Nt,l==r) return (void)++O[rt].g;RI mid=l+r>>1;
}
public:
I void Init(CI _n) {Build(1,n=_n,Rt[0]);}
I bool Identify(CI v,CI x,CI y) {return getfa(Rt[v],x)==getfa(Rt[v],y);}//判断是否连通
I void Union(CI v,CI x,CI y)//按秩合并
{
Rt[v]=Rt[v-1];RI fx=getfa(Rt[v],x),fy=getfa(Rt[v],y);if(fx==fy) return;
O[fx].g<O[fy].g&&swap(fx,fy),Upt(O[fy].f,O[fx].f,1,n,Rt[v]),
}
}U;
int main()
{
freopen("history.in","r",stdin),freopen("history.out","w",stdout);
}