可持久化并查集

没有想到 这么好写 就是用可持久化数组 维护了 我们并查集 之前的fa 数字 和 dep 数组

从历史版本 合并 查询
当然 这里我们不能路径压缩 只能 安秩合并 降低复杂度
路径压缩复杂度是均摊的,无法可持久化(复杂度可以被卡成暴力)
https://www.acwing.com/problem/content/272/
https://www.luogu.org/problem/P3402

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
typedef long long ll;

int n, m;
struct node {
	int lc, rc;
	int val, siz;
} tr[maxn * 40];
int tot, root[maxn << 1];

int build(int l, int r) {
	int p = ++ tot;
	if(l == r) {
		tr[p].val = l;
		tr[p].siz = 1;
		return p;
	}
	int mid = l + r >> 1;
	tr[p].lc = build(l, mid);
	tr[p].rc = build(mid + 1, r);
	return p;
}

int updata(int now, int L, int l, int r, int val, int siz) {
	int p = ++ tot;
	tr[p] = tr[now];
	if(l == r) {
		tr[p].val = val;
		tr[p].siz = siz;
		return p;
	}
	int mid = l + r >> 1;
	if(L <= mid) tr[p].lc = updata(tr[now].lc, L, l, mid, val, siz);
	else tr[p].rc = updata(tr[now].rc, L, mid + 1, r, val, siz);
	return p;
}

node query(int now, int L, int l, int r) {
	if(l == r) {
		return tr[now];
	}
	int mid = l + r >> 1;
	if(L <= mid) return query(tr[now].lc, L, l, mid);
	else return query(tr[now].rc, L, mid + 1, r);
}

node finds(int now, int x) {
	node pre = query(now, x, 1, n);
	if(pre.val != x) return finds(now, pre.val);
	return pre;
}

void unions(int k, int last, int a, int b) {
	node x = finds(root[k], a), y = finds(root[k], b);
	if(x.val != y.val) {
		if(x. siz > y.siz) swap(x, y);
		root[k] = updata(root[last], x.val, 1, n, y.val, x.siz);
		root[k] = updata(root[k], y.val, 1, n, y.val, x.siz + y.siz);
	}
}

signed main() {
	scanf("%d %d", &n, &m);
	root[0] = build(1, n);
	int pre = 0;
	for(int i = 1, op, k, a, b; i <= m; ++ i) {
		root[i] = root[i - 1];
		scanf("%d", &op);
		if(op == 1) {
			a ^= pre, b ^= pre;
			scanf("%d %d", &a, &b);
			unions(i, i - 1,a, b);
		} else if(op == 2) {
			scanf("%d", &k);
			k ^= pre;
			root[i] = root[k];
		} else {
			scanf("%d %d", &a, &b);
			a ^= pre, b ^= pre;
			pre = int(finds(root[i], a).val == finds(root[i], b).val);
			printf("%d\n", pre);
		}
	}
	return 0;
}