1.利用权值线段树实现
# 【模板】普通平衡树
## 题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入 $x$ 数
2. 删除 $x$ 数(若有多个相同的数,应只删除一个)
3. 查询 $x$ 数的排名(排名定义为比当前数小的数的个数 $+1$ )
4. 查询排名为 $x$ 的数
5. 求 $x$ 的前驱(前驱定义为小于 $x$,且最大的数)
6. 求 $x$ 的后继(后继定义为大于 $x$,且最小的数)
运用到了离散化操作
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
const int maxn = 100001 + 10;
int b[maxn], cnt;
struct lisan {
int x, q;
} offline[maxn];
struct node {
int l, r;
int val;
} tree[maxn << 2];
void build(int rt, int l, int r) {
tree[rt].l = l;
tree[rt].r = r;
tree[rt].val = 0;
if (tree[rt].l == tree[rt].r) {
return ;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
}
int query(int root, int l, int r) {
if (l <= tree[root].l && tree[root].r <= r) {
return tree[root].val;
}
int mid = (tree[root].l + tree[root].r) >> 1;
int ans = 0;
if (l <= mid) {
ans += query(root << 1, l, r);
}
if (r > mid) {
ans += query(root << 1 | 1, l, r);
}
return ans;
}
void update(int root, int x, int p) {
if (tree[root].l == tree[root].r) {
tree[root].val += p;
return ;
}
int mid = (tree[root].l + tree[root].r) >> 1;
if (x <= mid) {
update(root << 1, x, p);
}
if (x > mid) {
update(root << 1 | 1, x, p);
}
tree[root].val = tree[root << 1].val + tree[root << 1 | 1].val;
}
int requery(int root, int len) {
if (tree[root].l == tree[root].r) {
return tree[root].l;
}
if (len <= tree[root << 1].val)
return requery(root << 1, len);
else {
return requery(root << 1 | 1, len - (tree[root << 1].val));
}
}
int main() {
cin >> n;
build(1, 1, 1e5);
for (int i = 1; i <= n; i++) {
cin >> offline[i].q >> offline[i].x;
if (offline[i].q != 4) {
b[++cnt] = offline[i].x;
}
}
sort(b + 1, b + 1 + cnt);
cnt = unique(b + 1, b + 1 + cnt) - (b + 1);
for (int i = 1; i <= n; i++) {
int x = offline[i].x;
if (offline[i].q != 4) {
x = lower_bound(b + 1, b + cnt + 1, x) - b; //找到x的索引
}
int ans;
switch (offline[i].q) {
case 1:
update(1, x, 1);
break;
case 2:
update(1, x, -1);
break;
case 3:
ans = query(1, 1, x - 1);
ans++;
cout << ans << endl;
break;
case 4:
ans = requery(1, x);
cout << b[ans] << endl;
break;
case 5:
ans = query(1, 1, x - 1);
ans = requery(1, ans);
cout << b[ans] << endl;
break;
case 6:
ans = query(1, 1, x);
ans = requery(1, ans + 1);
cout << b[ans] << endl;
break;
}
}
}