您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
标签:one tor aws cstring void 数据 数据结构 查询 desc
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
对于操作3,4,5,6每行输出一个数,表示对应答案
作为一个模板题放在这里,准备写5个平衡树。算是个坑...
一般平衡树的操作,不多赘述。
我们考虑删除数$x$:我们将$x$的前驱和后继找到。两个找到之后再将前驱通过$splay$操作旋到根,再将后继旋成前驱的儿子,删除后继的左儿子即可。
显然能够保证后继的左儿子只有一个。
至于为什么要前驱和后继都找到之后再旋转,是因为查找的时候会将其他的节点旋转到根。
我们通过维护子树大小来实现这一功能。
某个数的名次其实就是当它旋转到根的时候左子树的大小+1。
我们对于每次插入操作,删除操作,$rotate$操作都要更新名次。
递归实现。
若左子树大小+1 <= 查询名次 <= 左子树大小+根节点数个数,结果就是当前数;
若查询名次 <= 左子树大小+1,递归查询左子树;
若查询名次 >= 左子树大小+根节点数个数,将查询名次-=左子树大小+根节点数个数,递归查询右子树。
通过$find$操作,找到“接近”这个数的数的位置。
为什么是“接近”,是因为可能$splay$中可能不存在这个数,不存在的话我们就假想最后停在的节点就是这个数。
将其旋到根。判断这个数与根节点的数的关系,若小于(即不存在查询的数)显然这个数就是前驱。
若非,就查询其左子树“最靠右的那个数”。
和查找前驱类似。
1 //It is made by Awson on 2017.11.28 2 #include <map> 3 #include <set> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define Max(a, b) ((a) > (b) ? (a) : (b)) 17 #define Min(a, b) ((a) < (b) ? (a) : (b)) 18 using namespace std; 19 const int N = 100000; 20 const int INF = ~0u>>1; 21 22 struct Splay_tree { 23 int pre[N+5], ch[N+5][2], key[N+5], size[N+5], cnt[N+5], tot, root; 24 queue<int>mem; 25 void newnode(int &o, int keyy, int fa) { 26 if (!mem.empty()) o = mem.front(), mem.pop(); 27 else o = ++tot; 28 pre[o] = fa, ch[o][0] = ch[o][1] = 0; 29 key[o] = keyy, cnt[o] = size[o] = 1; 30 } 31 void pushup(int o) { 32 size[o] = size[ch[o][0]]+size[ch[o][1]]+cnt[o]; 33 } 34 void rotate(int o, int kind) { 35 int p = pre[o]; 36 ch[p][!kind] = ch[o][kind], pre[ch[o][kind]] = p; 37 ch[pre[p]][ch[pre[p]][1] == p] = o, pre[o] = pre[p]; 38 ch[o][kind] = p, pre[p] = o; 39 pushup(p), pushup(o); 40 } 41 void splay(int o, int goal) { 42 while (pre[o] != goal) { 43 if (pre[pre[o]] == goal) rotate(o, ch[pre[o]][0] == o); 44 else { 45 int p = pre[o], kind = ch[pre[p]][0] == p; 46 if (ch[p][kind] == o) rotate(o, !kind), rotate(o, kind); 47 else rotate(p, kind), rotate(o, kind); 48 } 49 } 50 if (goal == 0) root = o; 51 } 52 void insert(int &o, int keyy, int fa) { 53 if (o == 0) { 54 newnode(o, keyy, fa); splay(o, 0); return; 55 } 56 size[o]++; 57 if (key[o] == keyy) { 58 cnt[o]++; splay(o, 0); return; 59 } 60 insert(ch[o][keyy > key[o]], keyy, o); 61 } 62 void find(int o, int keyy) { 63 if (o == 0) return; 64 if (key[o] == keyy) { 65 splay(o, 0); return; 66 } 67 if (ch[o][keyy > key[o]]) find(ch[o][keyy > key[o]], keyy); 68 else splay(o, 0); 69 } 70 int get_las(int keyy) { 71 find(root, keyy); 72 if (keyy > key[root]) return root; 73 int u = ch[root][0]; 74 while (ch[u][1]) u = ch[u][1]; 75 return u; 76 } 77 int get_nex(int keyy) { 78 find(root, keyy); 79 if (keyy < key[root]) return root; 80 int u = ch[root][1]; 81 while (ch[u][0]) u = ch[u][0]; 82 return u; 83 } 84 void delet(int keyy) { 85 int las = get_las(keyy); 86 int nex = get_nex(keyy); 87 splay(las, 0), splay(nex, las); 88 size[las]--, size[nex]--; 89 if (cnt[ch[nex][0]] > 1) { 90 cnt[ch[nex][0]]--; size[ch[nex][0]]--; 91 splay(ch[nex][0], 0); 92 }else { 93 mem.push(ch[nex][0]); 94 ch[nex][0] = 0; 95 } 96 } 97 int Kth(int o, int rest) { 98 if (rest >= size[ch[o][0]]+1 && rest <= size[ch[o][0]]+cnt[o]) return o; 99 if (rest > size[ch[o][0]]+cnt[o]) return Kth(ch[o][1], rest-size[ch[o][0]]-cnt[o]); 100 return Kth(ch[o][0], rest); 101 } 102 }S; 103 int n, opt, x; 104 105 void work() { 106 S.insert(S.root, INF, 0); 107 S.insert(S.root, -INF, 0); 108 scanf("%d", &n); 109 while (n--) { 110 scanf("%d%d", &opt, &x); 111 if (opt == 1) S.insert(S.root, x, 0); 112 else if (opt == 2) S.delet(x); 113 else if (opt == 3) { 114 S.find(S.root, x); 115 printf("%d\n", S.size[S.ch[S.root][0]]); 116 }else if (opt == 4) printf("%d\n", S.key[S.Kth(S.root, x+1)]); 117 else if (opt == 5) printf("%d\n", S.key[S.get_las(x)]); 118 else if (opt == 6) printf("%d\n", S.key[S.get_nex(x)]); 119 } 120 } 121 int main() { 122 work(); 123 return 0; 124 }
标签:one tor aws cstring void 数据 数据结构 查询 desc
原文地址:http://www.cnblogs.com/NaVi-Awson/p/7919884.html