为何这个fhq代码开O2就全RE,不开O2就AC
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, tot, root;
struct FHQ {
int l, r;
int val, key, size;
} t[N];
int New(int x) {
tot++;
t[tot].l = t[tot].r = 0, t[tot].size = 1;
t[tot].val = x, t[tot].key = rand();
return tot;
}
void update(int p) {
t[p].size = t[t[p].l].size + t[t[p].r].size + 1;
}
// 权值分裂,返回以 L 和 R 为根的两棵树
void split(int p, int x, int &L, int &R) {
if (p == 0) { // 到达叶子,递归返回
L = R = 0;
return;
}
if (t[p].val <= x) { // 本节点比 x 小,到右子树上找
L = p; // 左树的根是本节点
split(t[p].r, x, t[p].r, R); // 通过右子树传回新的子节点
}
else {
R = p;
split(t[p].l, x, L, t[p].l);
}
update(p);
}
// 合并以 L 和 R 为根的两棵树,返回一棵树的根
int merge(int L, int R) {
if (L == 0 || R == 0) return L + R; // 到达叶子,若 L 等于 0,就是返回 L+R=R
if (t[L].key > t[R].key) { // 左树 L 优先级大于右树 R,则 L 节点是父节点
t[L].r = merge(t[L].r, R); // 合并 R 和 L 的右儿子,并更新 L 的右儿子
update(L);
return L; // 返回合并后的根 L
}
else {
t[R].l = merge(L, t[R].l);
update(R);
return R;
}
}
int Insert(int x) {
int L, R;
split(root, x, L, R);
root = merge(merge(L, New(x)), R);
}
int Remove(int x) {
int L, R, p;
split(root, x, L, R); // 小于等于 x 的树和大于 x 的树
split(L, x - 1, L, p); // 小于 x 的树和等于 x 的树
p = merge(t[p].l, t[p].r); // 合并 x=p 的左右两子树,相当于删除 x
root = merge(merge(L, p), R);
}
void get_rank_by_val(int x) {
int L, R;
split(root, x - 1, L, R); // 小于 x 的树和大于等于 x 的树
cout << t[L].size + 1 << endl;
root = merge(L, R); // 恢复
}
int get_val_by_rank(int p, int k) {
if (k == t[t[p].l].size + 1) return p; // 这个数为根
if (k <= t[t[p].l].size) return get_val_by_rank(t[p].l, k); // 在左子树
if (k > t[t[p].l].size) return get_val_by_rank(t[p].l, k - t[t[p].l].size - 1); // 在右子树
}
void get_pre(int x) {
int L, R;
split(root, x - 1, L, R);
cout << t[get_val_by_rank(L, t[L].size)].val << endl;
root = merge(L, R);
}
void get_next(int x) {
int L, R;
split(root, x, L, R);
cout << t[get_val_by_rank(R, 1)].val << endl;
root = merge(L, R);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
srand(time(NULL));
cin >> n;
while (n--) {
int opt, x;
cin >> opt >> x;
switch (opt) {
case 1:
Insert(x);
break;
case 2:
Remove(x);
break;
case 3:
get_rank_by_val(x);
break;
case 4:
cout << t[get_val_by_rank(root, x)].val << endl;
break;
case 5:
get_pre(x);
break;
case 6:
get_next(x);
break;
}
}
return 0;
}