tyvj 普通平衡树为例。
题目描述
这是一道模板题。
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 x xx 数;
- 删除 x xx 数(若有多个相同的数,因只删除一个);
- 查询 x xx 数的排名(若有多个相同的数,因输出最小的排名);
- 查询排名为 x xx 的数;
- 求 x xx 的前趋(前趋定义为小于 x xx,且最大的数);
- 求 x xx 的后继(后继定义为大于 x xx,且最小的数)。
输入格式
第一行为 n nn,表示操作的个数,下面 n nn 行每行有两个数 opt \mathrm{opt}opt 和 x xx,opt \mathrm{opt}opt 表示操作的序号(1≤opt≤6 1 \leq \mathrm{opt} \leq 61≤opt≤6)。
输出格式
对于操作 3、4、5、6 每行输出一个数,表示对应答案。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 7 using namespace std; 8 9 const int N = 110000 * 35; 10 11 int ch[N][2], sum[N], tot = 1; 12 13 #define walk for(int i = 31, t, rt = 1 ; (t = (val >> i) & 1), ~i ; i --) 14 15 void ins(int val, int c = 1) { 16 walk { 17 if(ch[rt][t] == 0) ch[rt][t] = ++ tot; 18 sum[rt = ch[rt][t]] += c; 19 } 20 } 21 22 int kth(int val, int ret = 0) { 23 walk { 24 if(val > sum[ch[rt][0]]) { 25 val -= sum[ch[rt][0]]; 26 ret |= 1 << i; 27 rt = ch[rt][1]; 28 } else { 29 rt = ch[rt][0]; 30 } 31 } 32 return ret; 33 } 34 35 int rk(int val, int ret = 0) { 36 walk { 37 ret += t * sum[ch[rt][0]]; 38 rt = ch[rt][t]; 39 } 40 return ret; 41 } 42 43 int pre(int val) { 44 return kth(rk(val)); 45 } 46 47 int sub(int val) { 48 return kth(rk(val + 1) + 1); 49 } 50 51 int n, opt, x; 52 53 int main() { 54 scanf("%d", &n); 55 for(int i = 1 ; i <= n ; i ++) { 56 scanf("%d%d", &opt, &x); 57 x += int(1e7); 58 if(opt == 1) ins(x); 59 if(opt == 2) ins(x, -1); 60 if(opt == 3) printf("%d\n", rk(x) + 1); 61 if(opt == 4) printf("%d\n", kth(x - (int)1e7) - (int)1e7); 62 if(opt == 5) printf("%d\n", pre(x) - (int)1e7); 63 if(opt == 6) printf("%d\n", sub(x) - (int)1e7); 64 } 65 }