1. 程式人生 > >[BZOJ3224]普通平衡樹

[BZOJ3224]普通平衡樹

hint esp treap tput center remove border 實現 out

題目描述 Description
您需要寫一種數據結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
1. 插入x數
2. 刪除x數(若有多個相同的數,因只刪除一個)
3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名)
4. 查詢排名為x的數
5. 求x的前驅(前驅定義為小於x,且最大的數)
6. 求x的後繼(後繼定義為大於x,且最小的數)
輸入描述 Input Description

第一行為n,表示操作的個數,下面n行每行有兩個數opt和x,opt表示操作的序號(1<=opt<=6)

輸出描述 Output Description
對於操作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
數據範圍及提示 Data Size & Hint
1.n的數據範圍:n<=100000
2.每個數的數據範圍:[-2e9,2e9]

最裸的平衡樹題。用treap來實現,由於是可重復的,我這裏默認如果鍵值相同就往左子樹插,然後一些經典操作例如什麽找前驅後繼,排名什麽的上面都寫了,希望當作以後的模板。

技術分享
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
#include<ctime>
using namespace std;
typedef long long
LL; #define mem(a,b) memset(a,b,sizeof(a)) inline int read() { int x=0,f=1;char c=getchar(); while(!isdigit(c)){if(c==-)f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-0;c=getchar();} return x*f; } const int maxn=100010,oo=2147483647; struct node { int val,rnd; int cmp(int v)const { if(val==v)return -1; return v<val ? 0 : 1; } }ns[maxn]; int tot,rt,ch[2][maxn],size[maxn]; int New(int v) { int o=++tot;ns[o].val=v;ns[o].rnd=rand(); ch[0][o]=ch[1][o]=0;return o; } void del(int o){ns[o].val=ns[o].rnd=ch[0][o]=ch[1][o]=size[o]=0;o=0;} void maintain(int o) { if(!o)return; size[o]=1; if(ch[0][o])size[o]+=size[ch[0][o]]; if(ch[1][o])size[o]+=size[ch[1][o]]; } void rotate(int &o,int d) { int k=ch[d^1][o];ch[d^1][o]=ch[d][k];ch[d][k]=o; maintain(o);o=k;return maintain(o); } void insert(int &o,int v) { if(!o){o=New(v);return maintain(o);} int d= v<=ns[o].val ? 0 : 1; insert(ch[d][o],v); if(ns[ch[d][o]].rnd>ns[o].rnd)rotate(o,d^1); return maintain(o); } void remove(int &o,int v) { if(!o)return; int d=ns[o].cmp(v); if(d==-1) { int t=o; if(ch[0][o] && ch[1][o]) { int d2= ns[ch[0][o]].rnd>ns[ch[1][o]].rnd ? 1 : 0; rotate(o,d2);remove(ch[d2][o],v); } else if(!ch[0][o])o=ch[1][o]; else o=ch[0][o]; del(t); } else remove(ch[d][o],v); return maintain(o); } int kth(int o,int k) { if(!o || k<0 || k>size[o])return 0; int s=size[ch[0][o]]; if(k==s+1)return ns[o].val; else if(k<=s)return kth(ch[0][o],k); else return kth(ch[1][o],k-s-1); } int rank(int o,int v) { if(!o)return 0; if(v>ns[o].val)return size[ch[0][o]]+1+rank(ch[1][o],v); return rank(ch[0][o],v); } int lower(int o,int v) { if(!o)return -oo; if(ns[o].val<v)return max(ns[o].val,lower(ch[1][o],v)); else return lower(ch[0][o],v); } int upper(int o,int v) { if(!o)return oo; if(ns[o].val>v)return min(ns[o].val,upper(ch[0][o],v)); else return upper(ch[1][o],v); } int n,tp,x; int main() { n=read(); while(n--) { tp=read();x=read(); if(tp==1)insert(rt,x); else if(tp==2)remove(rt,x); else if(tp==3)printf("%d\n",rank(rt,x)+1); else if(tp==4)printf("%d\n",kth(rt,x)); else if(tp==5)printf("%d\n",lower(rt,x)); else if(tp==6)printf("%d\n",upper(rt,x)); } return 0; }
View Code

[BZOJ3224]普通平衡樹