01trie(平衡树)

 

tyvj 普通平衡树为例。

 

题目描述

这是一道模板题。

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入 x xx 数;
  2. 删除 x xx 数(若有多个相同的数,因只删除一个);
  3. 查询 x xx 数的排名(若有多个相同的数,因输出最小的排名);
  4. 查询排名为 x xx 的数;
  5. 求 x xx 的前趋(前趋定义为小于 x xx,且最大的数);
  6. 求 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 61opt6)。

输出格式

对于操作 3、4、5、6 每行输出一个数,表示对应答案。

 

 

 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 }
View Code

 

posted @ 2017-08-18 17:10  KingSann  阅读(524)  评论(0编辑  收藏  举报