https://www.lydsy.com/JudgeOnline/problem.php?id=3674
用可持久化数组维护并查集的fa数组,
查询时间复杂度为nlognlogn,一个log是并查集的时间复杂度,采用按秩合并的操作,需要注意的是按秩合并的秩意思为当前最大结点下的树的最大深度。
另一个log是主席树查询的时间复杂度
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Sca2(x,y) scanf("%d%d",&x,&y) #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d ", x) #define Prl(x) printf("%lld ",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second typedef vector<int> VI; int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();} while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;} const double eps = 1e-9; const int maxn = 2e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,K; int T[maxn],tot; struct Tree{ int lt,rt; int fa,size; }tree[maxn * 52]; int fa[maxn],Size[maxn]; void newnode(int &t){ t = ++tot; tree[t].lt = tree[t].rt = tree[t].fa = 0; } void Build(int &t,int l,int r){ newnode(t); if(l == r){ tree[t].fa = l; tree[t].size = 0; return; } int m = l + r >> 1; Build(tree[t].lt,l,m); Build(tree[t].rt,m + 1,r); } int query(int t,int l,int r,int x){ if(l == r){ Size[x] = tree[t].size; return tree[t].fa; } int m = l + r >> 1; if(x <= m) return query(tree[t].lt,l,m,x); else return query(tree[t].rt,m + 1,r,x); } void update(int &t,int pre,int l,int r,int x){ newnode(t); tree[t] = tree[pre]; if(l == r){ tree[t].fa = fa[x]; tree[t].size = Size[x]; return; } int m = l + r >> 1; if(x <= m) update(tree[t].lt,tree[pre].lt,l,m,x); else update(tree[t].rt,tree[pre].rt,m + 1,r,x); } int find(int id,int x){ int f = query(T[id],1,N,x); if(f == x) return x; return find(id,f); } int main(){ //freopen("C.in","r",stdin); Sca2(N,M); Build(T[0],1,N); int ans = 0; for(int i = 1; i <= M; i ++){ int op = read(); if(op == 1){ int a = read() ^ ans,b = read() ^ ans; a = find(i - 1,a); b = find(i - 1,b); if(Size[a] > Size[b]) swap(a,b); fa[a] = b; update(T[i],T[i - 1],1,N,a); if(Size[a] == Size[b]){ Size[b]++; fa[b] = b; int x; update(x,T[i],1,N,b); T[i] = x; } }else if(op == 2){ int k = read() ^ ans; T[i] = T[k]; }else if(op == 3){ T[i] = T[i - 1]; int a = read() ^ ans,b = read() ^ ans; a = find(i,a); b = find(i,b); ans = (a == b); if(a == b) puts("1"); else puts("0"); } } return 0; }