题目合集:

  1. 维护递增的中序遍历

    P3369 【模板】普通平衡树

  2. 按题目要求维护的中序遍历(中序遍历维护序列)

    P3391 【模板】文艺平衡树

    操作合集+Splay建树:P2042 [NOI2005] 维护数列

  3. Splay 合并

    P3224 [HNOI2012]永无乡

注意事项:

  1. 题目「普通平衡树」中函数 precidnexid 中的变量 ans 初值应设为比哨兵节点的更小和更大,如哨兵节点设为 NINFINF,则 ans 初值可设为 NINF - 1INF + 1

Luogu P3369 【模板】普通平衡树

代码:

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include<bits/stdc++.h>
using namespace std;
const int MAXn = 1e5;
const int INF = 0x3f3f3f3f;
const int NINF = 0xc0c0c0c0;

template <typename T>
inline void read(T &a) {
char c;for (c = getchar(); (c < '0' || c > '9') && c != '-'; c = getchar());bool f = c == '-';T x = f ? 0 : (c ^ '0');for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) {x = x * 10 + (c ^ '0');}a = f ? -x : x;
}
template <typename T, typename ...Argv>
inline void read(T &a, Argv &...argv) {
read(a), read(argv...);
}

int cntnd, root, son[MAXn + 10][2], fa[MAXn + 10];
int cnt[MAXn + 10], siz[MAXn + 10], val[MAXn + 10];
inline void pushup(int id) {
siz[id] = cnt[id] + siz[son[id][0]] + siz[son[id][1]];
}
inline bool side(int id) {
return son[fa[id]][1] == id;
}
inline void rotate(int id) {
int y = fa[id], z = fa[y], sideid = side(id), s = son[id][sideid ^ 1];
if (z) {son[z][side(y)] = id;} fa[id] = z;
son[y][sideid] = s; if (s) {fa[s] = y;}
son[id][sideid ^ 1] = y; fa[y] = id;
pushup(y); pushup(id);
}
inline void splay(int id, int goal = 0) {
int y;
while (fa[id] != goal) {
y = fa[id];
if (fa[y] != goal) {
if (side(id) == side(y)) rotate(y);
else rotate(id);
}
rotate(id);
}
if (goal == 0) root = id;
}
void build() {
cntnd = 2; root = 1;
son[1][1] = 2; cnt[1] = 1; siz[1] = 2; val[1] = NINF;
fa[2] = 1; cnt[2] = 1; siz[2] = 1; val[2] = INF;
}
int valtorank(int v) {
int ans = 1, id = root, faid = 0;
while (id) {
faid = id;
if (v < val[id]) {
id = son[id][0];
} else if (v == val[id]) {
ans += siz[son[id][0]];
break;
} else {
ans += siz[son[id][0]] + cnt[id];
id = son[id][1];
}
}
splay(faid);
return ans;
}
int ranktoid(int rk) {
int id = root;
while (true) {
if (rk <= siz[son[id][0]]) {
id = son[id][0];
} else if (rk <= siz[son[id][0]] + cnt[id]) {
break;
} else {
rk -= siz[son[id][0]] + cnt[id];
id = son[id][1];
}
}
splay(id);
return id;
}
int precid(int v) {
int ans = NINF - 1, anser = -1, id = root, faid = 0;
while (id) {
faid = id;
if (val[id] >= v) {
id = son[id][0];
} else {
if (ans < val[id]) {
ans = val[id];
anser = id;
}
id = son[id][1];
}
}
splay(faid);
return anser;
}
int nexid(int v) {
int ans = INF + 1, anser = -1, id = root, faid = 0;
while (id) {
faid = id;
if (val[id] <= v) {
id = son[id][1];
} else {
if (ans > val[id]) {
ans = val[id];
anser = id;
}
id = son[id][0];
}
}
splay(faid);
return anser;
}
void insert(int v) {
int prec = precid(v), nex = nexid(v);
splay(prec); splay(nex, prec);
int id = son[nex][0];
if (id == 0) {
id = ++cntnd;
son[nex][0] = id; fa[id] = nex;
val[id] = v;
}
++cnt[id];
pushup(id); pushup(nex); pushup(prec);
}
void delet(int v) {
int prec = precid(v), nex = nexid(v);
splay(prec); splay(nex, prec);
int id = son[nex][0];
if (id == 0) return;
--cnt[id];
pushup(id); pushup(nex); pushup(prec);
if (cnt[id] == 0) {
son[nex][0] = 0;
}
}

int n;
signed main() {
build();
read(n);
for (int i = 1, opt, x; i <= n; ++i) {
read(opt, x);
if (opt == 1) insert(x);
else if (opt == 2) delet(x);
else if (opt == 3) printf("%d\n", valtorank(x) - 1);
else if (opt == 4) printf("%d\n", val[ranktoid(x + 1)]);
else if (opt == 5) printf("%d\n", val[precid(x)]);
else if (opt == 6) printf("%d\n", val[nexid(x)]);
}
return 0;
}

Luogu P3391 【模板】文艺平衡树

代码:

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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include<bits/stdc++.h>
using namespace std;
const int MAXn = 1e5;
const int INF = 0x3f3f3f3f;
const int NINF = 0xc0c0c0c0;

template <typename T>
inline void read(T &a) {
char c;for (c = getchar(); (c < '0' || c > '9') && c != '-'; c = getchar());bool f = c == '-';T x = f ? 0 : (c ^ '0');for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) {x = x * 10 + (c ^ '0');}a = f ? -x : x;
}
template <typename T, typename ...Argv>
inline void read(T &a, Argv &...argv) {
read(a), read(argv...);
}

int cntnd, root, son[MAXn + 10][2], fa[MAXn + 10];
int siz[MAXn + 10], val[MAXn + 10];
int lzrev[MAXn + 10];
inline void putrev(int id) {
swap(son[id][0], son[id][1]);
lzrev[id] ^= 1;
}
inline void pushdown(int id) {
if (lzrev[id]) {
if (son[id][0]) putrev(son[id][0]);
if (son[id][1]) putrev(son[id][1]);
lzrev[id] = 0;
}
}
inline void pushup(int id) {
siz[id] = 1 + siz[son[id][0]] + siz[son[id][1]];
}
inline bool side(int id) {
return son[fa[id]][1] == id;
}
inline void rotate(int id) {
int y = fa[id], z = fa[y], sideid = side(id), s = son[id][sideid ^ 1];
if (z) {son[z][side(y)] = id;} fa[id] = z;
son[y][sideid] = s; if (s) {fa[s] = y;}
son[id][sideid ^ 1] = y; fa[y] = id;
pushup(y); pushup(id);
}
inline void splay(int id, int goal = 0) {
int y;
while (fa[id] != goal) {
y = fa[id];
if (fa[y] != goal) {
if (side(id) == side(y)) rotate(y);
else rotate(id);
}
rotate(id);
}
if (goal == 0) root = id;
}
int build2(int l, int r, int f) {
int rt = ++cntnd, mid = (l + r) >> 1;
fa[rt] = f;
val[rt] = mid;
if (l < mid) son[rt][0] = build2(l, mid - 1, rt);
if (r > mid) son[rt][1] = build2(mid + 1, r, rt);
pushup(rt);
return rt;
}
void build1(int n) {
cntnd = 2; root = 1;
son[1][1] = 2; val[1] = NINF;
fa[2] = 1; val[2] = INF;
son[2][0] = build2(1, n, 2);
pushup(2); pushup(1);
}
int ranktoid(int rk) {
int id = root;
while (true) {
pushdown(id);
if (rk <= siz[son[id][0]]) {
id = son[id][0];
} else if (rk <= siz[son[id][0]] + 1) {
break;
} else {
rk -= siz[son[id][0]] + 1;
id = son[id][1];
}
}
splay(id);
return id;
}
void modifyrev(int l, int r) {
int prec = ranktoid(l - 1), nex = ranktoid(r + 1);
splay(prec); splay(nex, prec);
int tar = son[nex][0];
if (tar) putrev(tar);
}
void traversal(int id) {
pushdown(id);
if (son[id][0]) traversal(son[id][0]);
if (val[id] != NINF && val[id] != INF) printf("%d ", val[id]);
if (son[id][1]) traversal(son[id][1]);
}

int n, m;
signed main() {
read(n, m);
build1(n);
for (int i = 1, l, r; i <= m; ++i) {
read(l, r);
modifyrev(l + 1, r + 1);
}
traversal(root);
puts("");
return 0;
}