题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224
题解:灵活运用,像这种不对区间操作的,相同的数放到一块就可以了
#include <bits/stdc++.h>
using namespace std;
#define INF 2e9 + 10
const int N = 1e5 + 10;
struct Splaytree {
int nex[N][2];
int f[N];
int sz[N]; // 子树节点个数
int val[N]; // 当前节点的值
int cnt[N]; // 当前节点个数
int root;
int tot;
void init() {
root = 0;
tot = 0;
f[0] = sz[0] = nex[0][0] = nex[0][1] = 0;
cnt[0] = 0;
}
void newnode(int rt, int v, int fa) {
f[rt] = fa;
sz[rt] = 1;
val[rt] = v;
cnt[rt] = 1;
nex[rt][0] = nex[rt][1] = 0;
}
void delnode(int rt) {
f[rt] = sz[rt] = val[rt] = cnt[rt] = 0;
nex[rt][0] = nex[rt][1] = 0;
}
void pushup(int rt) {
if(!rt) return;
sz[rt] = cnt[rt];
if(nex[rt][0]) sz[rt] += sz[nex[rt][0]];
if(nex[rt][1]) sz[rt] += sz[nex[rt][1]];
}
void build(int &rt, int l, int r, int fa) {
if(l > r) return;
int mid = (l + r) >> 1;
rt = mid;
newnode(rt, val[rt], fa);
cnt[rt] = 1;
build(nex[rt][0], l, mid - 1, rt);
build(nex[rt][1], mid + 1, r, rt);
}
void rotate(int x, int k) { // 0:左旋 1:右旋
int y = f[x];
int z = f[y];
nex[y][!k] = nex[x][k];
if(nex[x][k]) f[nex[x][k]] = y;
f[x] = z;
if(z) nex[z][nex[z][1] == y] = x;
f[y] = x;
nex[x][k] = y;
pushup(y);
pushup(x);
}
void splay(int x, int goal) { // x 旋转到 goal下面
while(f[x] != goal) {
if(f[f[x]] == goal) rotate(x, nex[f[x]][0] == x);
else {
int y = f[x], z = f[y];
int K = (nex[z][0] == y);
if(nex[y][K] == x) rotate(x, !K), rotate(x, K);
else rotate(y, K), rotate(x, K);
}
}
pushup(x);
if(goal == 0) root = x;
}
int search(int rt, int x) { // 查询权值为x的节点
if(nex[rt][0] && val[rt] > x) return search(nex[rt][0], x);
else if(nex[rt][1] && val[rt] < x) return search(nex[rt][1], x);
else return rt;
}
int extreme(int rt, int k) { // 子树最值节点 0小 1大
while(nex[rt][k]) rt = nex[rt][k];
splay(rt, 0);
return rt;
}
int getkth(int rt, int k) {
if(sz[nex[rt][0]] < k && k <= sz[nex[rt][0]] + cnt[rt]) return rt;
else if(sz[nex[rt][0]] >= k) return getkth(nex[rt][0], k);
else return getkth(nex[rt][1], k - sz[nex[rt][0]] - cnt[rt]);
}
int prec(int x) { // 前驱
int k = search(root, x);
splay(k, 0);
if(val[k] < x) return k;
return extreme(nex[k][0], 1);
}
int sufc(int x) { // 后继
int k = search(root, x);
splay(k, 0);
if(val[k] > x) return k;
return extreme(nex[k][1], 0);
}
void insert(int x) { // 插入
int y = search(root, x);
if(val[y] == x) {
cnt[y]++;
sz[y]++;
for(int k = y; k; k = f[k]) pushup(k);
splay(y, 0);
} else {
int p = prec(x);
int s = sufc(x);
splay(p, 0);
splay(s, p);
newnode(++tot, x, nex[root][1]);
nex[nex[root][1]][0] = tot;
for(int k = nex[root][1]; k; k = f[k]) pushup(k);
}
}
void delete_(int x) { // 删除
int y = search(root, x);
if(val[y] != x) return;
if(cnt[y] > 1) {
cnt[y]--;
sz[y]--;
for(int k = y; k; k = f[k]) pushup(k);
} else if(nex[y][0] == 0 || nex[y][1] == 0) {
int z = f[y];
nex[z][nex[z][1] == y] = nex[y][nex[y][0] == 0];
f[nex[y][nex[y][0] == 0]] = z;
delnode(y);
for(int k = z; k; k = f[k]) pushup(k);
} else {
int p = prec(x);
int s = sufc(x);
splay(p, 0);
splay(s, p);
nex[nex[root][1]][0] = 0;
delnode(nex[nex[root][1]][0]);
for(int k = s; k; k = f[k]) pushup(k);
}
}
int getrank(int x) { // 某权值的排名
int k = search(root, x);
splay(k, 0);
return sz[nex[k][0]] + 1;
}
}p;
int n;
int main() {
scanf("%d", &n);
p.init();
p.val[1] = -INF;
p.val[2] = INF;
p.tot = 2;
p.build(p.root, 1, 2, 0);
p.pushup(p.root);
int op, x;
for(int i = 1; i <= n; i++) {
scanf("%d %d", &op, &x);
if(op == 1) p.insert(x);
else if(op == 2) p.delete_(x);
else if(op == 3) printf("%d\n", p.getrank(x) - 1);
else if(op == 4) printf("%d\n", p.val[p.getkth(p.root, x + 1)]);
else if(op == 5) printf("%d\n", p.val[p.prec(x)]);
else printf("%d\n", p.val[p.sufc(x)]);
}
return 0;
}