Luogu 3402 可持久化并查集
点开这题纯属无聊……不过既然写掉了,那就丢一个模板好了
不得不说,可持久化并查集实现真的很暴力,就是把并查集的数组弄一个主席树可持久化。
有一点要注意的是不能写路径压缩,这样跳版本的时候会错,所以弄一个按秩合并来降低时间复杂度。
总时间复杂度$O(nlog^2n)$。
听说用siz实现按秩合并会比较好,因为这样还能查询集合大小,有时间以后补上。
Code:
#include <cstdio> using namespace std; const int N = 1e5 + 5; const int M = 2e5 + 5; int n, qn; inline void read(int &X) { X = 0; char ch = 0; int op = 1; for(; ch > '9'|| ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } struct Node { int lc, rc, dep, fa; }; namespace PUfs { Node s[N * 120]; int root[M * 2], nodeCnt; #define mid ((l + r) >> 1) void build(int &p, int l, int r) { p = ++nodeCnt; if(l == r) { s[p].fa = l; return; } build(s[p].lc, l, mid); build(s[p].rc, mid + 1, r); } void modify(int &p, int l, int r, int x, int f, int pre) { p = ++nodeCnt; if(l == r) { s[p].fa = f; s[p].dep = s[pre].dep; return; } s[p].lc = s[pre].lc, s[p].rc = s[pre].rc; if(x <= mid) modify(s[p].lc, l, mid, x, f, s[pre].lc); else modify(s[p].rc, mid + 1, r, x, f, s[pre].rc); } void add(int p, int l, int r, int x) { if(l == r) { s[p].dep++; return; } if(x <= mid) add(s[p].lc, l, mid, x); else add(s[p].rc, mid + 1, r, x); } int query(int p, int l, int r, int x) { if(l == r) return p; if(x <= mid) return query(s[p].lc, l, mid, x); else return query(s[p].rc, mid + 1, r, x); } int find(int now, int x) { int f = query(now, 1, n, x); if(s[f].fa == x) return f; return find(now, s[f].fa); } } using namespace PUfs; inline void print(int p) { printf("%d: ", p); for(int j = 1; j <= n; j++) printf("%d ", s[find(root[p], j)].fa); /* for(int j = 1; j <= n; j++) printf("%d ", query(root[p], 1, n, j)); */ printf("\n"); } inline void swap(int &x, int &y) { int t = x; x = y; y = t; } int main() { read(n), read(qn); nodeCnt = 0; build(root[0], 1, n); // print(0); for(int op, i = 1; i <= qn; i++) { read(op); if(op == 1) { root[i] = root[i - 1]; int x, y; read(x), read(y); int fx = find(root[i], x), fy = find(root[i], y); if(s[fx].fa == s[fy].fa) continue; if(s[fx].dep > s[fy].dep) swap(fx, fy); modify(root[i], 1, n, s[fx].fa, s[fy].fa, root[i - 1]); if(s[fx].dep == s[fy].dep) add(root[i], 1, n, s[fy].fa); } if(op == 2) { int k; read(k); root[i] = root[k]; } if(op == 3) { root[i] = root[i - 1]; int x, y; read(x), read(y); int fx = find(root[i], x), fy = find(root[i], y); if(s[fx].fa == s[fy].fa) puts("1"); else puts("0"); } // print(i); } return 0; }