1. 程式人生 > >bzoj 3224 Tyvj 1728 普通平衡樹

bzoj 3224 Tyvj 1728 普通平衡樹

大小 題目 tput sub 最大的 數據結構 color see 相同

Tyvj 1728 普通平衡樹

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 17187 Solved: 7501
[Submit][Status][Discuss]

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] 題解:是用treap去維護,當然c++的STL也可以過(不知道為什麽), 這些都是treap的基本操作,復雜度是O(n log n)的。
  1
#include<cstring> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #include<cstdio> 6 7 #define ls tr[p].l 8 #define rs tr[p].r 9 #define N 100007 10 #define inf 2000000010 11 using namespace std; 12 inline int read() 13 { 14 int
x=0,f=1;char ch=getchar(); 15 while(ch<0||ch>9){if (ch==-)f=-1;ch=getchar();} 16 while(ch>=0&&ch<=9){x=(x<<3)+(x<<1)+ch-0;ch=getchar();} 17 return x*f; 18 } 19 20 int n,sz,rt,ans; 21 struct Node 22 { 23 int l,r,val,siz,rnd,ct;//記錄左兒子,右兒子,點值,該子樹大小,隨機的值,該點值出現的次數。 24 }tr[N];//最多多少個節點,就開多少空間 25 26 inline int rand(){ 27 static int seed = 2333; 28 return seed = (int)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007); 29 } 30 inline void update(int p) 31 { 32 tr[p].siz=tr[ls].siz+tr[rs].siz+tr[p].ct; 33 } 34 void lturn(int &p) 35 { 36 int t=tr[p].r;tr[p].r=tr[t].l;tr[t].l=p; 37 tr[t].siz=tr[p].siz;update(p);p=t; 38 } 39 void rturn(int &p) 40 { 41 int t=tr[p].l;tr[p].l=tr[t].r;tr[t].r=p; 42 tr[t].siz=tr[p].siz;update(p);p=t; 43 } 44 void ins(int &p,int x) 45 { 46 if (p==0) 47 { 48 p=++sz; 49 tr[p].siz=tr[p].ct=1,tr[p].val=x,tr[p].rnd=rand(); 50 return; 51 } 52 tr[p].siz++; 53 if (tr[p].val==x) tr[p].ct++; 54 else if (x>tr[p].val) 55 { 56 ins(tr[p].r,x); 57 if (tr[rs].rnd<tr[p].rnd) lturn(p); 58 }else 59 { 60 ins(tr[p].l,x); 61 if (tr[ls].rnd<tr[p].rnd) rturn(p); 62 } 63 } 64 void del(int &p,int x) 65 { 66 if (p==0) return; 67 if (tr[p].val==x) 68 { 69 if (tr[p].ct>1) tr[p].ct--,tr[p].siz--;//如果有多個直接減一即可。 70 else 71 { 72 if (ls==0||rs==0) p=ls+rs;//單節點或者空的話直接兒子移上來或者刪去即可。 73 else if (tr[ls].rnd<tr[rs].rnd) rturn(p),del(p,x); 74 else lturn(p),del(p,x); 75 } 76 } 77 else if (x>tr[p].val) tr[p].siz--,del(rs,x); 78 else tr[p].siz--,del(ls,x); 79 } 80 int find_pm(int p,int x) 81 { 82 if (p==0) return 0; 83 if (tr[p].val==x) return tr[ls].siz+1; 84 if (x>tr[p].val) return tr[ls].siz+tr[p].ct+find_pm(rs,x); 85 else return find_pm(ls,x); 86 } 87 int find_sz(int p,int x) 88 { 89 if (p==0) return 0; 90 if (x<=tr[ls].siz) return find_sz(ls,x); 91 x-=tr[ls].siz; 92 if (x<=tr[p].ct) return tr[p].val; 93 x-=tr[p].ct; 94 return find_sz(rs,x); 95 } 96 int find_qq(int p,int x) 97 { 98 if (p==0) return -inf; 99 if (tr[p].val<x) return max(tr[p].val,find_qq(rs,x)); 100 else if (tr[p].val>=x) return find_qq(ls,x); 101 } 102 int find_hj(int p,int x) 103 { 104 if (p==0) return inf; 105 if (tr[p].val<=x) return find_hj(rs,x); 106 else return min(tr[p].val,find_hj(ls,x)); 107 } 108 int main() 109 { 110 n=read(); 111 for (int i=1;i<=n;i++) 112 { 113 int flag=read(),x=read(); 114 if (flag==1) ins(rt,x); 115 if (flag==2) del(rt,x); 116 if (flag==3) printf("%d\n",find_pm(rt,x));//尋找x的排名 117 if (flag==4) printf("%d\n",find_sz(rt,x));//尋找排名為x的數字 118 if (flag==5) printf("%d\n",find_qq(rt,x)); 119 if (flag==6) printf("%d\n",find_hj(rt,x)); 120 } 121 }

bzoj 3224 Tyvj 1728 普通平衡樹