BZOJ 3673 3674

3673
3674

使用线段树作为可持久化数据结构维护朴素并查集中的fa数组

用到的都是可持久化线段树的基本操作

3674还需要路径压缩

用3674的代码改掉强制在线交到3673上过了以后去交3674,但是忘了把强制在线改回来……结果直接过了……WNM


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//3674
#include <bits/stdc++.h>

struct seg {
int l, r, lc, rc, fa;
} s[200010 * 20 * 2];

int root[200010], tot = 0;

int build(int l, int r) {
int t = ++ tot;
s[t].l = l;
s[t].r = r;
if (l == r) {
s[tot].fa = l;
return t;
}
int mid = l + r >> 1;
s[t].lc = build(l, mid);
s[t].rc = build(mid + 1, r);
return t;
}

int findfa(int t, int k) {
if (s[t].l == s[t].r)
return s[t].fa;
int mid = s[t].l + s[t].r >> 1;
if (k <= mid)
return findfa(s[t].lc, k);
else
return findfa(s[t].rc, k);
}

void insert(int &t, int pt, int k, int fa) {
t = ++ tot;
s[t] = s[pt];
if (s[t].l == s[t].r) {
s[t].fa = fa;
return;
}
int mid = s[t].l + s[t].r >> 1;
if (k <= mid)
insert(s[t].lc, s[pt].lc, k, fa);
else
insert(s[t].rc, s[pt].rc, k, fa);
}

int getfa(int i, int t) {
int fa = findfa(root[i], t);
if (fa == t)
return t;
int faa = getfa(i, fa);
insert(root[i], root[i], t, faa);
return faa;
}

int main() {
int n, m;
scanf("%d%d", &n, &m);
root[0] = build(1, n);
int a, b, c;
int ans = 0;
for (int i = 1; i <= m; i ++) {
scanf("%d", &c);
if (c == 1) {
scanf("%d%d", &a, &b);
a ^= ans, b ^= ans;
root[i] = root[i - 1];
insert(root[i], root[i - 1], getfa(i, a), getfa(i, b));
}
if (c == 2) {
scanf("%d", &a);
a ^= ans;
root[i] = root[a];
}
if (c == 3) {
scanf("%d%d", &a, &b);
a ^= ans, b ^= ans;
root[i] = root[i - 1];
if (getfa(i, a) == getfa(i, b))
ans = 1;
else
ans = 0;
printf("%d\n", ans);
ans = 0; // <- 不把这一行删掉也tm能过
}
}
return 0;
}

3673的代码就不贴了