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
int root;
int cntnd;
int fa[MAXn + 10], son[MAXn + 10][2], hig[MAXn + 10];
int val[MAXn + 10], cnt[MAXn + 10], siz[MAXn + 10];
inline void pushup(int id) {
hig[id] = max(hig[son[id][0]], hig[son[id][1]]) + 1;
siz[id] = siz[son[id][0]] + siz[son[id][1]] + cnt[id];
}
inline int 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 avl(int id) {
if (abs(hig[son[id][0]] - hig[son[id][1]]) >= 2) {
int b = hig[son[id][0]] < hig[son[id][1]], big = son[id][b];
if (hig[son[big][b]] < hig[son[big][b ^ 1]]) rotate(son[big][b ^ 1]);
int nwrt = son[id][b];
rotate(nwrt);
if (fa[nwrt] == 0) root = nwrt;
}
}
int top, stk[MAXn + 10];
void Insert(int v) {
int id = root;
top = 0;
while (id) {
stk[++top] = id;
if (v < val[id]) id = son[id][0];
else if (v > val[id]) id = son[id][1];
else break;
}
if (id) {
++cnt[id];
while (top) pushup(stk[top--]);
} else {
++cntnd;
if (stk[top]) son[stk[top]][v > val[stk[top]]] = cntnd;
else root = cntnd;
fa[cntnd] = stk[top];
hig[cntnd] = 1;
val[cntnd] = v;
cnt[cntnd] = 1;
siz[cntnd] = 1;
while (top) {
pushup(stk[top]);
avl(stk[top]);
--top;
}
}
}
void Delete(int v) {
int id = root;
top = 0;
while (id) {
stk[++top] = id;
if (v < val[id]) id = son[id][0];
else if (v > val[id]) id = son[id][1];
else break;
}
if (id) {
--cnt[id];
if (cnt[id]) {
while (top) pushup(stk[top--]);
} else {
if (son[id][0] == 0 && son[id][1] == 0) {
if (top) --top;
if (stk[top]) son[stk[top]][val[id] > val[stk[top]]] = 0;
else root = 0;
} else if (son[id][0] == 0 || son[id][1] == 0) {
if (top) --top;
int s = son[id][son[id][0] == 0];
if (stk[top]) {
son[stk[top]][val[id] > val[stk[top]]] = s;
fa[s] = stk[top];
} else {
root = s;
fa[s] = 0;
}
} else {
int pre = son[id][0];
while (pre) {
stk[++top] = pre;
pre = son[pre][1];
}
pre = stk[top--];
val[id] = val[pre];
cnt[id] = cnt[pre];
son[stk[top]][stk[top] != id] = son[pre][0];
if (son[pre][0]) fa[son[pre][0]] = stk[top];
}
while (top) {
pushup(stk[top]);
avl(stk[top]);
--top;
}
}
}
}
int ValtoRank(int v) {
int id = root, ans = 1;
while (id) {
if (v < val[id]) {
id = son[id][0];
} else if (v > val[id]) {
ans += siz[son[id][0]] + cnt[id];
id = son[id][1];
} else {
ans += siz[son[id][0]];
break;
}
}
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]) {
return id;
} else {
rk -= siz[son[id][0]] + cnt[id];
id = son[id][1];
}
}
}
int PreId(int v) {
return RanktoId(ValtoRank(v) - 1);
}
int NexId(int v) {
return RanktoId(ValtoRank(v + 1));
}