#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct Treap {
private :
int nodecnt, pool[N], poolcnt, root;
int son[N][2], val[N], prio[N], cnt[N], siz[N];
void init() { nodecnt = poolcnt = root = son[0][0] = son[0][1] = prio[0] = siz[0] = 0; }
void pushup(int cur) { siz[cur] = siz[son[cur][0]] + siz[son[cur][1]] + 1; }
void newnode(int& cur, int x) {
cur = poolcnt ? pool[poolcnt --] : ++ nodecnt;
son[cur][0] = son[cur][1] = 0, val[cur] = x, prio[cur] = rand(), cnt[cur] = siz[cur] = 1;
}
void rotate(int& cur, int f) { // 以 cur 为根的子树旋转并把 cur 更新为新的根节点编号,f 为 0 表示左旋
int t = son[cur][f ^ 1];
son[cur][f ^ 1] = son[t][f], son[t][f] = cur, pushup(cur), pushup(t), cur = t;
}
void insert(int& cur, int x) { // x 存在则找到 x 的位置 cnt ++,否则找到要插入的叶节点的位置
if (! cur) return newnode(cur, x);
if (x == val[cur]) return cnt[cur] ++, siz[cur] ++, void(); // cnt ++ 即可
int f = x > val[cur];
insert(son[cur][f], x), pushup(cur);
if (prio[son[cur][f]] > prio[cur]) rotate(cur, f ^ 1); // 回溯的时候顺便向上调整维护堆
}
void remove(int& cur, int x) { // x 存在且 cnt > 1 则 cnt --,否则将要删除的点移到叶节点删除
if (! (son[cur][0] | son[cur][1])) { // 到叶节点自动删除
if (cur) pool[++ poolcnt] = cur;
return cur = 0, void();
}
if (x == val[cur] && cnt[cur] > 1) cnt[cur] --, siz[cur] --; // cnt -- 即可
else if (x == val[cur]) { // 将当前节点移到叶节点
int f = prio[son[cur][1]] > prio[son[cur][0]];
rotate(cur, f ^ 1), remove(son[cur][f ^ 1], x), pushup(cur);
}
else remove(son[cur][x > val[cur]], x), pushup(cur); // 继续往下找
}
int rank(int cur, int x) { // cur 为根的子树内比 x 小的数的个数
if (! cur) return 0;
if (x == val[cur]) return siz[son[cur][0]];
if (x < val[cur]) return rank(son[cur][0], x);
return siz[son[cur][0]] + cnt[cur] + rank(son[cur][1], x);
}
int kth(int cur, int k) { // cur 为根的子树内排名为 k 的数
if (siz[cur] < k || k <= 0) return -1;
if (k <= siz[son[cur][0]]) return kth(son[cur][0], k);
if (k <= siz[son[cur][0]] + cnt[cur]) return val[cur];
return kth(son[cur][1], k - siz[son[cur][0]] - cnt[cur]);
}
public :
void ins(int x) { insert(root, x); }
void rem(int x) { remove(root, x); }
int ran(int x) { return rank(root, x) + 1; }
int kth(int k) { return kth(root, k); }
int pre(int x) { return kth(ran(x) - 1); } // 最大的比 x 小的数
int nxt(int x) { return kth(ran(x + 1)); } // 最小的比 x 大的数
} treap;
int main() {
srand(time(0));
int n; scanf("%d", &n);
for (int i = 1, op, x; i <= n; i ++) {
scanf("%d%d", &op, &x);
if (op == 1) treap.ins(x);
else if (op == 2) treap.rem(x);
else if (op == 3) printf("%d\n", treap.ran(x));
else if (op == 4) printf("%d\n", treap.kth(x));
else if (op == 5) printf("%d\n", treap.pre(x));
else if (op == 6) printf("%d\n", treap.nxt(x));
}
return 0;
}
有错的地方应该是 siz 的维护