BZOJ 3673 & 3674 可持久化并查集
用可持久化线段树维护并查集的fa数组
要按秩合并
好久不写,有点生疏。
修改时都要开新节点,这样才不会影响之前的版本
#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define lp tree[p].l
#define rp tree[p].r
const int N = 2e5 + 7;
struct Node {
int l, r;
};
int n;
struct Seg {
Node tree[N * 50];
int tol;
void build(int &p, int l, int r) {
if (!p) p = ++tol;
if (l == r) {
tree[p].l = l;
tree[p].r = 1;
return;
}
build(lp, l, mid);
build(rp, mid + 1, r);
}
void update(int &p, int l, int r, int pos, Node v) {
tree[++tol] = tree[p];
p = tol;
if (l == r) {
tree[p] = v;
return;
}
if (pos <= mid) update(lp, l, mid, pos, v);
else update(rp, mid + 1, r, pos, v);
}
Node query(int p, int l, int r, int pos) {
if (l == r) return tree[p];
if (pos <= mid) return query(lp, l, mid, pos);
return query(rp, mid + 1, r, pos);
}
Node find(int p, int x) {
Node temp = query(p, 1, n, x);
if (temp.l == x) return temp;
return find(p, temp.l);
}
} seg;
int root[N], m, ans;
int main() {
scanf("%d%d", &n, &m);
seg.build(root[0], 1, n);
for (int opt, l, r, k, i = 1; i <= m; i++) {
scanf("%d", &opt);
root[i] = root[i - 1];
if (opt == 1) {
scanf("%d%d", &l, &r);
l ^= ans, r ^= ans;
Node fx = seg.find(root[i], l), fy = seg.find(root[i], r);
if (fx.l == fy.l) continue;
if (fx.r > fy.r) std::swap(fx, fy);
seg.update(root[i], 1, n, fx.l, {fy.l, fx.r});
seg.update(root[i], 1, n, fy.l, {fy.l, fx.r + fy.r});
} else if (opt == 2) {
scanf("%d", &k);
k ^= ans;
root[i] = root[k];
} else {
scanf("%d%d", &l, &r);
l ^= ans, r ^= ans;
Node fx = seg.find(root[i], l), fy = seg.find(root[i], r);
ans = fx.l == fy.l;
printf("%d\n", ans);
}
}
return 0;
}