3224: Tyvj 1728 普通平衡树
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]
第一次这么仔细的打平衡树。但方法绝不仅仅止于此。
因为是裸题,所以可以用:
- 树状数组fenwick
- 线段树(因为树状数组可以)
- 近乎于暴力的vector
- 平衡树家族
- 红黑树rbt
- 节点大小平衡树sbt
- splay
- 替罪羊树sgt
- treap
1 /************************************************************** 2 Problem: 3224 3 User: Doggu 4 Language: C++ 5 Result: Accepted 6 Time:304 ms 7 Memory:3164 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <algorithm> 13 #define sm(a,b,c) {if(c==0) a=std::max(a,b);else a=std::min(a,b);} 14 template<class T> inline void readin(T &res) { 15 static char ch;T flag=1; 16 while((ch=getchar())<48||ch>57)if(ch=='-')flag=-1; 17 res=ch-48; 18 while((ch=getchar())>=48&&ch<=57)res=(res<<1)+(res<<3)+ch-'0'; 19 res*=flag; 20 } 21 const int N = 100005; 22 const int INF = 0x3f3f3f3f; 23 struct Node { 24 int key, w, size, rd; 25 Node *ch[2]; 26 int cmp(int x) { 27 if(x==key) return -1; 28 return x>key; 29 } 30 void maintain() {size = ch[0]->size + ch[1]->size + w;} 31 }pool[N], *tail=pool, *root=pool, *null=pool; 32 int rand() { 33 static int seed=1000007; 34 return seed=(int)seed*48271LL%2147483647; 35 } 36 Node* newnode() { 37 Node *nd = tail++; 38 nd->rd=rand();nd->ch[0]=nd->ch[1]=null; 39 return nd; 40 } 41 void rotate(Node *&nd,int d) {//d=0 right(1) to left(0) d=1 left(0) to right(1) 42 Node *k=nd->ch[d^1];nd->ch[d^1]=k->ch[d];k->ch[d]=nd; 43 nd->maintain();k->maintain();nd=k; 44 } 45 void insert(Node *&nd,int x) { 46 if(nd==null) nd=newnode(),nd->key=x,nd->w=1; 47 else { 48 int d=nd->cmp(x); 49 if(d==-1) nd->w++; 50 else { 51 insert(nd->ch[d],x); 52 if(nd->ch[d]->rd>nd->rd) rotate(nd,d^1); 53 } 54 } 55 nd->maintain(); 56 } 57 void del(Node *&nd,int x) { 58 if(nd==null) return ; 59 int d=nd->cmp(x); 60 if(d==-1) { 61 if(nd->w>1) nd->w--; 62 else if(nd->ch[0] == null) nd=nd->ch[1]; 63 else if(nd->ch[1] == null) nd=nd->ch[0]; 64 else if(nd->ch[1]>nd->ch[0]) rotate(nd,0),del(nd->ch[0],x); 65 else rotate(nd,1),del(nd->ch[1],x); 66 } else del(nd->ch[d],x); 67 nd->maintain(); 68 } 69 int find(Node *nd,int x) { 70 while(nd!=null) { 71 int d=nd->cmp(x); 72 if(d==-1) return 1; 73 nd=nd->ch[d]; 74 } 75 return 0; 76 } 77 int rnk(Node *nd,int x) { 78 int d=nd->cmp(x); 79 if(d==-1) return nd->ch[0]->size+1; 80 if(d==0) return rnk(nd->ch[0],x); 81 return nd->ch[0]->size+nd->w+rnk(nd->ch[1],x); 82 } 83 int kth(Node *nd,int x) { 84 if(x<=nd->ch[0]->size) return kth(nd->ch[0],x); 85 if(nd->ch[0]->size<x && x<=nd->ch[0]->size+nd->w) return nd->key; 86 return kth(nd->ch[1],x-nd->ch[0]->size-nd->w); 87 } 88 int temp; 89 void near(Node *nd,int x,int delta) { 90 if(nd==null) return ; 91 int d=nd->cmp(x); 92 if(d==!delta) sm(temp,nd->key,delta); 93 if(d==-1) near(nd->ch[delta],x,delta); 94 else near(nd->ch[d],x,delta); 95 } 96 97 /*void print(Node *nd) { 98 if(nd==null) return ; 99 print(nd->ch[0]); 100 for( int i = 1; i <= nd->w; i++ ) printf("%d ",nd->key); 101 print(nd->ch[1]); 102 }*/ 103 104 int main() { 105 //freopen("in.txt","r",stdin); 106 //freopen("out.txt","w",stdout); 107 null=newnode(); 108 int n, opt, x; 109 readin(n); 110 for( int i = 1; i <= n; i++ ) { 111 readin(opt);readin(x); 112 if(opt==1) {//插入x数 113 insert(root,x); 114 }else if(opt==2) {//删除x数(若有多个相同的数,因只删除一个) 115 del(root,x); 116 }else if(opt==3) {//查询x数的排名(若有多个相同的数,因输出最小的排名) 117 if(find(root,x)) printf("%d ",rnk(root,x)); 118 }else if(opt==4) {//查询排名为x的数 119 if(root->size>=x) printf("%d ",kth(root,x)); 120 }else if(opt==5) {//求x的前驱 121 temp=-INF;near(root,x,0);if(temp!=-INF)printf("%d ",temp); 122 }else if(opt==6) {//求x的后继 123 temp=INF;near(root,x,1);if(temp!=INF)printf("%d ",temp); 124 } 125 //printf("SEQ:");print(root);putchar(' '); 126 } 127 return 0; 128 } 129