bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5354 Solved: 2196
[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.每个数的数据范围:[-1e7,1e7]
【思路】
Rank tree
Treap实现名次树。需要多维护s,w域分别表示节点数目与相同键值的数目,相应修改maintain,remove和rank操作。
需要注意的是不能单单在insert的时候安排相同结点放在右子,因为有可能结点通过旋转转上来,这就违反了我们的初衷。
【代码】
1 #include<cstdio> 2 #include<ctime> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 7 using namespace std; 8 9 struct Node{ 10 Node* ch[2]; 11 int v,r,s,w; 12 Node(int x):v(x) { ch[0]=ch[1]=NULL; s=w=1; r=rand(); } 13 void maintain() { 14 s=w; //change 15 if(ch[0]!=NULL) s+=ch[0]->s; 16 if(ch[1]!=NULL) s+=ch[1]->s; 17 } 18 int cmp(int x) const { 19 if(x==v) return -1; return x<v?0:1; 20 } 21 }; 22 void rotate(Node* &o,int d) { 23 Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; 24 o->maintain(); k->maintain(); o=k; 25 } 26 //不能只是把大于等于x的放在右子树 有可能旋上来 27 void insert(Node* &o,int x) { 28 if(o==NULL) o=new Node(x); 29 else { 30 int d=o->cmp(x); 31 if(d==-1) { o->w++; o->maintain(); return; } //相同键值的个数 32 insert(o->ch[d],x); 33 if(o->ch[d]->r > o->r) rotate(o,d^1); 34 } 35 o->maintain(); 36 } 37 void remove(Node* &o,int x){ 38 if(o==NULL) return ; 39 int d=o->cmp(x); 40 if(d==-1) { 41 Node* u=o; 42 if(o->w>1) { o->w--; o->maintain(); return ; } //change2 43 if(o->ch[0]!=NULL && o->ch[1]!=NULL) { 44 int d2=o->ch[0]->r > o->ch[1]->r? 1:0; 45 rotate(o,d2); remove(o->ch[d2],x); 46 } 47 else { 48 if(o->ch[0]!=NULL) o=o->ch[0]; else o=o->ch[1]; 49 delete u; 50 } 51 } 52 else remove(o->ch[d],x); 53 if(o!=NULL) o->maintain(); 54 } 55 int kth(Node* o,int k) { 56 if(o==NULL || k<=0 || k>o->s) return 0; 57 int s=o->ch[0]==NULL? 0:o->ch[0]->s,w=o->w; 58 if(s+1<=k && k<=s+w) return o->v; 59 else if(k<=s) return kth(o->ch[0],k); 60 else return kth(o->ch[1],k-s-w); 61 } 62 int rank(Node* o,int x) { 63 if(o==NULL) return 0; 64 int d=o->cmp(x),s=o->ch[0]==NULL?0:o->ch[0]->s; 65 int f= d==1? s+o->w:0; 66 if(d==-1) return s+1; 67 else return rank(o->ch[d],x)+f; 68 } 69 void query1(Node* o,int x,int& ans) { 70 if(o==NULL) return ; 71 if(o->v<x) { ans=o->v; query1(o->ch[1],x,ans); } 72 else query1(o->ch[0],x,ans); 73 } 74 void query2(Node* o,int x,int& ans) { 75 if(o==NULL) return ; 76 if(o->v>x) { ans=o->v; query2(o->ch[0],x,ans); } 77 else query2(o->ch[1],x,ans); 78 } 79 int n,opt,x,ans; 80 Node* root=NULL; 81 82 int main() { 83 //srand(time(0)); //bzoj上不要用 否则RE 84 scanf("%d",&n); 85 FOR(i,1,n) { 86 scanf("%d%d",&opt,&x); 87 switch(opt) { 88 case 1: insert(root,x); break; 89 case 2: remove(root,x); break; 90 case 3: printf("%d\n",rank(root,x)); break; 91 case 4: printf("%d\n",kth(root,x)); break; 92 case 5: ans=0; query1(root,x,ans); printf("%d\n",ans); break; 93 case 6: ans=0; query2(root,x,ans); printf("%d\n",ans); break; 94 } 95 } 96 return 0; 97 }
posted on 2015-12-04 14:16 hahalidaxin 阅读(239) 评论(0) 编辑 收藏 举报