constexpr int N = 100005;
int rt, tot, fa[N], ch[N][2], val[N], cnt[N], sz[N];
struct Splay {
void maintain(int x) {
sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + cnt[x];
}
bool get(int x) {
return x == ch[fa[x]][1];
}
void clear(int x) {
ch[x][0] = ch[x][1] = fa[x] = val[x] = sz[x] = cnt[x] = 0;
}
void rotate(int x) {
int y = fa[x], z = fa[y], chk = get(x);
ch[y][chk] = ch[x][chk ^ 1];
if (ch[x][chk ^ 1]) {
fa[ch[x][chk ^ 1]] = y;
}
ch[x][chk ^ 1] = y;
fa[y] = x, fa[x] = z;
if (z) {
ch[z][y == ch[z][1]] = x;
}
maintain(y);
maintain(x);
}
void splay(int x) {
for (int f = fa[x]; f = fa[x], f; rotate(x)) {
if (fa[f]) {
rotate(get(x) == get(f) ? f : x);
}
}
rt = x;
}
void splay(int x, int k) {
while (fa[x] != k) {
int y = fa[x], z = fa[y];
if (z != k) {
if ((ch[y][1] == x) ^ (ch[z][1] == y)) {
rotate(x);
} else {
rotate(y);
}
}
rotate(x);
}
if (!k) {
rt = x;
}
}
int ins(int k) {
if (!rt) {
val[++tot] = k;
cnt[tot]++;
rt = tot;
maintain(rt);
return tot;
}
int cur = rt, f = 0;
while (true) {
if (val[cur] == k) {
cnt[cur]++;
maintain(cur);
maintain(f);
splay(cur);
return cur;
}
f = cur;
cur = ch[cur][val[cur] < k];
if (!cur) {
val[++tot] = k;
cnt[tot]++;
fa[tot] = f;
ch[f][val[f] < k] = tot;
maintain(tot);
maintain(f);
splay(tot);
return tot;
}
}
}
int rk(int k) {
int res = 0, cur = rt;
while (true) {
if (k < val[cur]) {
cur = ch[cur][0];
} else {
res += sz[ch[cur][0]];
if (k == val[cur]) {
splay(cur);
return res + 1;
}
res += cnt[cur];
cur = ch[cur][1];
}
}
}
int kth(int k) {
int cur = rt;
while (true) {
if (ch[cur][0] && k <= sz[ch[cur][0]]) {
cur = ch[cur][0];
} else {
k -= cnt[cur] + sz[ch[cur][0]];
if (k <= 0) {
return val[cur];
}
cur = ch[cur][1];
}
}
}
int pre() {
int cur = ch[rt][0];
if (!cur) {
return cur;
}
while (ch[cur][1]) {
cur = ch[cur][1];
}
splay(cur);
return cur;
}
int nxt() {
int cur = ch[rt][1];
if (!cur) {
return cur;
}
while (ch[cur][0]) {
cur = ch[cur][0];
}
splay(cur);
return cur;
}
int pre(int k) {
int cur = rt, id;
while (cur) {
if (val[cur] >= k) {
id = cur;
cur = ch[cur][0];
} else {
cur = ch[cur][1];
}
}
return id;
}
int nxt(int k) {
int cur = rt, id;
while (cur) {
if (val[cur] <= k) {
id = cur;
cur = ch[cur][1];
} else {
cur = ch[cur][0];
}
}
return id;
}
int get_k(int k) {
int cur = rt;
while (cur) {
if (val[cur] < k) {
cur = ch[cur][1];
} else if (val[cur] > k) {
cur = ch[cur][0];
} else {
return cur;
}
}
return -1;
}
void del(int k) {
rk(k);
if (cnt[rt] > 1) {
cnt[rt]--;
maintain(rt);
return;
}
if (!ch[rt][0] && !ch[rt][1]) {
clear(rt);
rt = 0;
return;
}
if (!ch[rt][0]) {
int cur = rt;
rt = ch[rt][1];
fa[rt] = 0;
clear(cur);
return;
}
if (!ch[rt][1]) {
int cur = rt;
rt = ch[rt][0];
fa[rt] = 0;
clear(cur);
return;
}
int cur = rt, x = pre();
fa[ch[cur][1]] = x;
ch[x][1] = ch[cur][1];
clear(cur);
maintain(rt);
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下