P3369 【模板】普通平衡树

题目描述

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

  1. 插入x数

  2. 删除x数(若有多个相同的数,因只删除一个)

  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

  4. 查询排名为x的数

  5. 求x的前驱(前驱定义为小于x,且最大的数)

  6. 求x的后继(后继定义为大于x,且最小的数)

输入输出格式

输入格式:

 

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 \leq opt \leq 61opt6 )

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 复制
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例#1: 复制
106465
84185
492737

说明

时空限制:1000ms,128M

1.n的数据范围: n \leq 100000n100000

2.每个数的数据范围: [-{10}^7, {10}^7][107,107]

来源:Tyvj1728 原名:普通平衡树

在此鸣谢

 

我是用来练习 可持久化Treap的。。

 1 #include <ctime>
 2 #include <cstdio>
 3 #include <cctype>
 4 #include <cstdlib>
 5 
 6 const int MAXN = 500010;
 7 
 8 int n, id;
 9 
10 int tree[MAXN][2], pri[MAXN], val[MAXN], siz[MAXN];
11 
12 inline void read(int&x) {
13     int f = 1; register char c = getchar();
14     for(x = 0; !isdigit(c); c == '-'&& (f = -1), c=getchar());
15     for(; isdigit(c); x = x * 10 + c - 48, c = getchar());
16     x = x * f;
17 }
18 
19 namespace Treap {
20     
21     int New(int v) {
22         siz[++id] = 1;
23         val[id] = v;
24         pri[id] = rand();
25         return id;
26     }
27     
28     void split(int now, int v, int&x, int&y) {
29         if(!now) {
30             x = y = 0;
31             return;
32         }
33         if(val[now] <= v) x = now, split(tree[now][1], v, tree[now][1], y);
34         else y = now, split(tree[now][0], v, x, tree[now][0]);
35         siz[now] = siz[tree[now][1]] + siz[tree[now][0]] + 1;
36     }
37     
38     int merge(int x,int y) {
39         if(!x || !y) return x + y;
40         if(pri[x] < pri[y]) {
41             tree[x][1] = merge(tree[x][1], y);
42             siz[x] = siz[tree[x][1]] + siz[tree[x][0]] + 1;
43             return x;
44         }
45         else {
46             tree[y][0] = merge(x, tree[y][0]);
47             siz[y] = siz[tree[y][1]] + siz[tree[y][0]] + 1;
48             return y;
49         }
50     }
51     
52     int kth(int now, int k) {
53         while(1) {
54             if(k <= siz[tree[now][0]]) now = tree[now][0];
55             else if(k == siz[tree[now][0]] + 1) return now;
56             else k -= siz[tree[now][0]] + 1, now = tree[now][1];
57         }
58     }
59 }
60 
61 int main(int argc,char**argv) {
62     read(n);
63     srand((unsigned)time(NULL));
64     int flag, v, root = 0, x, y, z;
65     for(int i = 1; i <= n; ++i) {
66         read(flag);read(v);
67         if(flag == 1) {
68             Treap::split(root, v, x, y);
69             root = Treap::merge(Treap::merge(x, Treap::New(v)), y);
70         }
71         else if(flag == 2) {
72             Treap::split(root, v, x, z);
73             Treap::split(x, v - 1, x, y);
74             y = Treap::merge(tree[y][0], tree[y][1]);
75             root = Treap::merge(Treap::merge(x, y), z);
76         }
77         else if(flag == 3) {
78             Treap::split(root, v - 1, x, y);
79             printf("%d\n",siz[x] + 1);
80             root = Treap::merge(x, y);
81         }
82         else if(flag == 4) printf("%d\n", val[Treap::kth(root, v)]);
83         else if(flag == 5) {
84             Treap::split(root, v - 1, x, y);
85             printf("%d\n",val[Treap::kth(x, siz[x])]);
86             root = Treap::merge(x, y);
87         }
88         else {
89             Treap::split(root, v, x, y);
90             printf("%d\n",val[Treap::kth(y, 1)]);
91             root = Treap::merge(x, y);
92         }
93     }
94     return 0;
95 }
代码

 

posted @ 2017-11-07 20:31  拿叉插猹哈  阅读(231)  评论(0编辑  收藏  举报