RT,调了很久,但不知道为什么 TLE了
#include <bits/stdc++.h>
constexpr int N = 1e6 + 10;
constexpr double alpha = 0.75; // 不平衡率,一般用 alpha 表示
using namespace std;
struct Node {
int left_son, right_son; // 左右儿子
int val; // 节点存的数字
int all_size; // 当前子树的节点数量,包括已被删除的节点
int size; // 子树上实际的存储数字的数量
int del; // del = 1 表示这个节点存有数字,反之被删除
}tree[N];
int order[N], cnt; // 记录被拍平后的结果,即那些存有数字的节点,cnt 为数量
int can_use_Nodes[N], top; // 可用节点
int root = 0; // 根节点,注意重建时根节点会发生变化
void in_order (int u) { // 中序遍历,“拍平”摧毁这棵子树
if (!u) return; // 已经到达叶子节点,退出
in_order(tree[u].left_son); // 先遍历左子树
if (tree[u].del) order[++cnt] = u; // 如果该节点有数字,读取它
else can_use_Nodes[++top] = u; // 回收该节点,等待重新分配使用
in_order(tree[u].right_son); // 再遍历右子树
}
void Initnode (int u) { // 重置节点参数
tree[u].left_son = tree[u].right_son = 0;
tree[u].size = tree[u].all_size = tree[u].del = 1;
}
void Update (int u) {
tree[u].size = tree[tree[u].left_son].size + tree[tree[u].right_son].size + 1;
tree[u].all_size = tree[tree[u].left_son].all_size + tree[tree[u].right_son].all_size + 1;
}
void build (int l, int r, int &u) { // 把拍平的子树拎起来,重建
int mid = (l + r) >> 1;
u = order[mid]; // 将新的根设为中点,使重构出的树尽量平衡
if (l == r) {
Initnode(u);
return;
} // 如果是叶子节点,返回
if (l < mid) build(l, mid - 1, tree[u].left_son); // 如果有左子树,重建左子树
if (l == mid) tree[u].left_son = 0; // 没有就把左儿子标记没有
build(mid + 1, r, tree[u].right_son); // 重构右子树
Update(u);
}
void rebuild(int &u) {
cnt = 0;
in_order(u);
if (cnt) build(1, cnt, u);
else u = 0;
}
bool not_balance(int u) {
double x = tree[u].size * alpha;
double y = max(tree[tree[u].left_son].size, tree[tree[u].right_son].size);
if (x <= y) return false;
return true;
}
void Insert(int &u, int x) {
if (!u) {
u = can_use_Nodes[top--];
tree[u].val = x;
Initnode(u);
return;
}
tree[u].size += 1;
tree[u].all_size += 1;
if (tree[u].val >= x) Insert(tree[u].left_son, x);
else Insert(tree[u].right_son, x);
if (not_balance(u)) rebuild(u);
}
int Rank(int u, int x) {
if (!u) return 0;
if (x > tree[u].val) return tree[tree[u].left_son].size + tree[u].del + Rank(tree[u].right_son, x);
return Rank(tree[u].left_son, x);
}
int kth(int k) {
int u = root;
while(u) {
if (tree[u].del && tree[tree[u].left_son].size + 1 == k)
return tree[u].val;
else if (tree[tree[u].left_son].size >= k)
u = tree[u].left_son;
else {
k = k - tree[tree[u].left_son].size - tree[u].del;
u = tree[u].right_son;
}
}
return tree[u].val;
}
void Del_k (int &u, int k) {
tree[u].size -= 1;
if (tree[u].del && tree[tree[u].left_son].size + 1 == k) {
tree[u].del = 0;
return;
}
if (tree[tree[u].left_son].size + tree[u].del >= k)
Del_k(tree[u].left_son, k);
else Del_k(tree[u].right_son, k - tree[tree[u].left_son].size - tree[u].del);
}
void Del(int x) {
Del_k(root, Rank(root, x) + 1);
if (tree[root].all_size * alpha >= tree[root].size) rebuild(root);
}
int main() {
for (int i = N - 1; i >= 1; --i) can_use_Nodes[++top] = i;
int q;
scanf("%d", &q);
while(q--) {
int opt, x; cin >> opt >> x;
switch(opt) {
case 1 : Insert(root, x); break;
case 2 : Del(x); break;
case 3 : printf("%d\n", Rank(root, x) + 1); break;
case 4 : printf("%d\n", kth(x)); break;
case 5 : printf("%d\n", kth(Rank(root, x))); break;
case 6 : printf("%d\n", kth(Rank(root, x + 1) + 1)); break;
}
}
}