3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 16072 Solved: 6973
[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
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
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
Source
----------------------------------------------------------------------------------------------------------------------------
感谢brian551神犇提供的模版orz
啃了一星期的平衡树,总算是啃下来了。
二叉搜索树+小/大根堆=Treap
讲得很详细:http://blog.csdn.net/u014634338/article/details/49612159
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define maxn 233333 5 struct node{ 6 int l,r,v,w,size,rnd; 7 }; 8 node tr[maxn*2]; 9 int read(); 10 void update(int); 11 void lturn(int&); 12 void rturn(int&); 13 void insert(int&,int); 14 void del(int&,int); 15 int query_rank(int,int); 16 int query_num(int,int); 17 void query_pro(int,int); 18 void query_sub(int,int); 19 int n,size,root,an; 20 int main(){ 21 n=read();size=0;root=0;an=0; 22 for(int i=1;i<=n;i++){ 23 int opt=read(),x=read(); 24 switch(opt){ 25 case 1: insert(root,x);break; 26 case 2: del(root,x);break; 27 case 3: printf("%d ",query_rank(root,x));break; 28 case 4: printf("%d ",query_num(root,x));break; 29 case 5: an=0;query_pro(root,x);printf("%d ",tr[an].v);break; 30 case 6: an=0;query_sub(root,x);printf("%d ",tr[an].v);break; 31 } 32 } 33 return 0; 34 } 35 void update(int k){ 36 tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w; 37 } 38 void lturn(int &k){ 39 int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k; 40 tr[t].size=tr[k].size;update(k);k=t; 41 } 42 void rturn(int &k){ 43 int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k; 44 tr[t].size=tr[k].size;update(k);k=t; 45 } 46 void insert(int &k,int x){ 47 if(k==0){ 48 k=++size; 49 tr[k].w=tr[k].size=1;tr[k].rnd=rand();tr[k].v=x; 50 return; 51 } 52 tr[k].size++; 53 if(tr[k].v==x) tr[k].w++; 54 else if(tr[k].v>x){ 55 insert(tr[k].l,x); 56 if(tr[k].rnd>tr[tr[k].l].rnd) rturn(k); 57 } 58 else{ 59 insert(tr[k].r,x); 60 if(tr[k].rnd>tr[tr[k].r].rnd) lturn(k); 61 } 62 } 63 void del(int &k,int x){ 64 if(k==0) return; 65 if(tr[k].v==x){ 66 if(tr[k].w>1){ 67 tr[k].w--;tr[k].size--;return; 68 } 69 if(tr[k].r*tr[k].l==0) k=tr[k].l+tr[k].r; 70 else if(tr[tr[k].l].rnd>tr[tr[k].r].rnd) lturn(k),del(k,x); 71 else rturn(k),del(k,x); 72 } 73 else if(tr[k].v>x) tr[k].size--,del(tr[k].l,x); 74 else tr[k].size--,del(tr[k].r,x); 75 } 76 int query_rank(int k,int x){ 77 if(k==0) return 0; 78 if(tr[k].v==x) return tr[tr[k].l].size+1; 79 else if(tr[k].v<x) return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x); 80 else return query_rank(tr[k].l,x); 81 } 82 int query_num(int k,int x){ 83 if(k==0) return 0; 84 if(x<=tr[tr[k].l].size) return query_num(tr[k].l,x); 85 else if(x>tr[tr[k].l].size+tr[k].w) return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w); 86 else return tr[k].v; 87 } 88 void query_pro(int k,int x){ 89 if(k==0) return; 90 if(x>tr[k].v) an=k,query_pro(tr[k].r,x); 91 else query_pro(tr[k].l,x); 92 } 93 void query_sub(int k,int x){ 94 if(k==0) return; 95 if(x<tr[k].v) an=k,query_sub(tr[k].l,x); 96 else query_sub(tr[k].r,x); 97 } 98 int read(){ 99 int ans=0,f=1;char c=getchar(); 100 while('0'>c||c>'9'){if(c=='-')f=-1;c=getchar();} 101 while('0'<=c&&c<='9')ans=ans*10+c-48,c=getchar();return ans*f; 102 }