题目链接
思路:
学习一下替罪羊树。 替罪羊树就是确定一个
α
α
因子,插入和常规平衡树插入无太大区别, 删除的时候节点还在, 只是做个标记已经删除过,然后查找和普通平衡树也没太大区别, 构建的时候当当前节点
x
x
的子树大小 * 某一个孩子子树的大小的时候, 暴力重建
x
x
子树就是了。的值一般取
0.7
0.7
。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 3e5 + 10;
const double alpha = 0.7;
using namespace std;
int stk[maxn], top, n, m, root;
int ls[maxn], rs[maxn], siz[maxn], travel[maxn];
int cnt[maxn], v[maxn], t1, goat;
bool exist[maxn];
int get_rank(int x) {
int now = root, ans = 1;
while(now) {
if(v[now] >= x) now = ls[now];
else {
ans += siz[ls[now]] + exist[now];
now = rs[now];
}
}
return ans;
}
void dfs(int rt) {
if(!rt) return ;
dfs(ls[rt]);
if(exist[rt]) travel[++t1] = rt;
else stk[++top] = rt;
dfs(rs[rt]);
}
void build(int &rt, int l, int r) {
int mid = (l + r) >> 1;
rt = travel[mid];
if(l == r) {
siz[rt] = cnt[rt] = 1;
ls[rt] = rs[rt] = 0;
return ;
}
if(l < mid) build(ls[rt], l, mid - 1);
else ls[rt] = 0;
if(mid < r) build(rs[rt], mid + 1, r);
else rs[rt] = 0;
siz[rt] = siz[ls[rt]] + siz[rs[rt]] + 1;
cnt[rt] = cnt[ls[rt]] + cnt[rs[rt]] + 1;
}
void rebuild(int &rt) {
t1 = 0; dfs(rt);
if(t1) build(rt, 1, t1);
else rt = 0;
}
void __insert(int &rt, int x) {
if(rt == 0) {
rt = stk[top--]; v[rt] = x;
siz[rt] = cnt[rt] = exist[rt] = 1;
ls[rt] = rs[rt] = 0;
return ;
} else {
siz[rt]++; cnt[rt]++;
if(x >= v[rt]) __insert(rs[rt], x);
else __insert(ls[rt], x);
if(siz[rt] * alpha < max(siz[ls[rt]], siz[rs[rt]])) rebuild(rt);
}
}
int get_kth(int x) {
int now = root;
while(now) {
if(exist[now] && siz[ls[now]] + 1 == x) return v[now];
if(x <= siz[ls[now]]) now = ls[now];
else {
x -= exist[now] + siz[ls[now]];
now = rs[now];
}
}
}
void __delete(int &rt, int rk) {
if(exist[rt] && rk == siz[ls[rt]] + 1) {
exist[rt] = false;
siz[rt]--; return ;
}
if(!rt) return ;
siz[rt]--;
if(rk <= siz[ls[rt]] + exist[rt]) __delete(ls[rt], rk);
else __delete(rs[rt], rk - exist[rt] - siz[ls[rt]]);
}
int main() {
scanf("%d", &n); root = 0;
for(int i = maxn - 2; i >= 1; i--) stk[++top] = i;
for(int i = 1; i <= n; i++) {
int opt, x;
scanf("%d %d", &opt, &x);
if(opt == 1) __insert(root, x);
if(opt == 2) __delete(root, get_rank(x));
if(opt == 3) printf("%d\n", get_rank(x));
if(opt == 4) printf("%d\n", get_kth(x));
if(opt == 5) printf("%d\n", get_kth(get_rank(x) - 1));
if(opt == 6) printf("%d\n", get_kth(get_rank(x + 1)));
}
return 0;
}