1. 程式人生 > >P3369 【模板】普通平衡樹

P3369 【模板】普通平衡樹

show int read 多個 () turn 時空 null 來源

題目描述

您需要寫一種數據結構(可參考題目標題),來維護一些數,其中需要提供以下操作:

  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 }
代碼

P3369 【模板】普通平衡樹