1. 程式人生 > >[BZOJ3224]普通平衡樹(旋轉treap)

[BZOJ3224]普通平衡樹(旋轉treap)

gree 答案 需要 discus space scrip 其中 個數 names

3224: Tyvj 1728 普通平衡樹

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 20328 Solved: 8979
[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]

Source

[Submit][Status][Discuss]

刷點模板題。。發現自己treap忘光了。。

沒什麽好說的,題目裏的排名是指從小到大,其余沒有什麽坑點,那些作為函數哪些作為過程要想清楚。

比無旋treap快,所以說到現在都沒有遇上必須用無旋treap的題,除了WC的那道可持久化treap。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define rep(i,l,r) for (int i=l; i<=r; i++)
 6
using namespace std; 7 8 const int N=100100,inf=1000000000; 9 int n,rt,nd,ans,op,x,ls[N],rs[N],sz[N],h[N],v[N],w[N]; 10 11 void rrot(int &x){ 12 int y=ls[x]; ls[x]=rs[y]; rs[y]=x; 13 sz[y]=sz[x]; sz[x]=sz[ls[x]]+sz[rs[x]]+w[x]; x=y; 14 } 15 16 void lrot(int &x){ 17 int y=rs[x]; rs[x]=ls[y]; ls[y]=x; 18 sz[y]=sz[x]; sz[x]=sz[ls[x]]+sz[rs[x]]+w[x]; x=y; 19 } 20 21 void ins(int &x,int k){ 22 if (!x){ 23 x=++nd; v[x]=k; h[x]=rand(); sz[x]=w[x]=1; return; 24 } 25 sz[x]++; 26 if (v[x]==k) { w[x]++; return; } 27 if (k<v[x]){ ins(ls[x],k); if (h[ls[x]]<h[x]) rrot(x);} 28 else { ins(rs[x],k); if (h[rs[x]]<h[x]) lrot(x); } 29 } 30 31 void del(int &x,int k){ 32 if (v[x]==k){ 33 if (w[x]>1) { w[x]--; sz[x]--; return; } 34 if (!ls[x] || !rs[x]) { x=ls[x]+rs[x]; return; } 35 if (h[ls[x]]<h[rs[x]]) rrot(x),del(x,k); else lrot(x),del(x,k); 36 return; 37 } 38 sz[x]--; 39 if (k<v[x]) del(ls[x],k); else del(rs[x],k); 40 } 41 42 int get(int x,int k){ 43 if (!x) return 0; 44 if (v[x]==k) return sz[ls[x]]+1; 45 else if (k<v[x]) return get(ls[x],k); else return sz[ls[x]]+w[x]+get(rs[x],k); 46 } 47 48 int find(int x,int k){ 49 if (!x) return 0; 50 if (sz[ls[x]]+1<=k && sz[ls[x]]+w[x]>=k) return v[x]; 51 if (sz[ls[x]]>=k) return find(ls[x],k); 52 else return find(rs[x],k-sz[ls[x]]-w[x]); 53 } 54 55 void pre(int x,int k){ 56 if (!x) return; 57 if (v[x]<k) ans=max(ans,v[x]),pre(rs[x],k); else pre(ls[x],k); 58 } 59 60 void nxt(int x,int k){ 61 if (!x) return; 62 if (v[x]>k) ans=min(ans,v[x]),nxt(ls[x],k); else nxt(rs[x],k); 63 } 64 65 int main(){ 66 freopen("bzoj3224.in","r",stdin); 67 freopen("bzoj3224.out","w",stdout); 68 for (scanf("%d",&n); n--; ){ 69 scanf("%d%d",&op,&x); 70 if (op==1) ins(rt,x); 71 if (op==2) del(rt,x); 72 if (op==3) printf("%d\n",get(rt,x)); 73 if (op==4) printf("%d\n",find(rt,x)); 74 if (op==5) ans=0,pre(rt,x),printf("%d\n",ans); 75 if (op==6) ans=inf,nxt(rt,x),printf("%d\n",ans); 76 } 77 return 0; 78 }

[BZOJ3224]普通平衡樹(旋轉treap)