码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ 3224]Tyvj 1728 普通平衡树

时间:2017-11-29 14:37:57      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:one   tor   aws   cstring   void   数据   数据结构   查询   desc   

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

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

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]

题解

作为一个模板题放在这里,准备写5个平衡树。算是个坑...

1 Splay

1.1 插入操作

一般平衡树的操作,不多赘述。

1.2 删除操作

我们考虑删除数$x$:我们将$x$的前驱和后继找到。两个找到之后再将前驱通过$splay$操作旋到根,再将后继旋成前驱的儿子,删除后继的左儿子即可。
显然能够保证后继的左儿子只有一个。
至于为什么要前驱和后继都找到之后再旋转,是因为查找的时候会将其他的节点旋转到根。

1.3 查询名次

我们通过维护子树大小来实现这一功能。
某个数的名次其实就是当它旋转到根的时候左子树的大小+1。
我们对于每次插入操作,删除操作,$rotate$操作都要更新名次。

1.4 查询Kth数

递归实现。
若左子树大小+1 <= 查询名次 <= 左子树大小+根节点数个数,结果就是当前数;
若查询名次 <= 左子树大小+1,递归查询左子树;
若查询名次 >= 左子树大小+根节点数个数,将查询名次-=左子树大小+根节点数个数,递归查询右子树。

1.5 查找前驱

通过$find$操作,找到“接近”这个数的数的位置。
为什么是“接近”,是因为可能$splay$中可能不存在这个数,不存在的话我们就假想最后停在的节点就是这个数。
将其旋到根。判断这个数与根节点的数的关系,若小于(即不存在查询的数)显然这个数就是前驱。
若非,就查询其左子树“最靠右的那个数”。

1.6 查找后继

和查找前驱类似。

技术分享图片
  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 }
Splay

 

[BZOJ 3224]Tyvj 1728 普通平衡树

标签:one   tor   aws   cstring   void   数据   数据结构   查询   desc   

原文地址:http://www.cnblogs.com/NaVi-Awson/p/7919884.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!