bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)
2015-12-04 14:16
393 查看
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
101 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
10646584185
492737
HINT
1.n的数据范围:n<=1000002.每个数的数据范围:[-1e7,1e7]
【思路】
Rank tree
Treap实现名次树。需要多维护s,w域分别表示节点数目与相同键值的数目,相应修改maintain,remove和rank操作。
需要注意的是不能单单在insert的时候安排相同结点放在右子,因为有可能结点通过旋转转上来,这就违反了我们的初衷。
【代码】
#include<cstdio> #include<ctime> #include<cstring> #include<cstdlib> #include<iostream> #define FOR(a,b,c) for(int a=(b);a<=(c);a++) using namespace std; struct Node{ Node* ch[2]; int v,r,s,w; Node(int x):v(x) { ch[0]=ch[1]=NULL; s=w=1; r=rand(); } void maintain() { s=w; //change if(ch[0]!=NULL) s+=ch[0]->s; if(ch[1]!=NULL) s+=ch[1]->s; } int cmp(int x) const { if(x==v) return -1; return x<v?0:1; } }; void rotate(Node* &o,int d) { Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->maintain(); k->maintain(); o=k; } //不能只是把大于等于x的放在右子树 有可能旋上来 void insert(Node* &o,int x) { if(o==NULL) o=new Node(x); else { int d=o->cmp(x); if(d==-1) { o->w++; o->maintain(); return; } //相同键值的个数 insert(o->ch[d],x); if(o->ch[d]->r > o->r) rotate(o,d^1); } o->maintain(); } void remove(Node* &o,int x){ if(o==NULL) return ; int d=o->cmp(x); if(d==-1) { Node* u=o; if(o->w>1) { o->w--; o->maintain(); return ; } //change2 if(o->ch[0]!=NULL && o->ch[1]!=NULL) { int d2=o->ch[0]->r > o->ch[1]->r? 1:0; rotate(o,d2); remove(o->ch[d2],x); } else { if(o->ch[0]!=NULL) o=o->ch[0]; else o=o->ch[1]; delete u; } } else remove(o->ch[d],x); if(o!=NULL) o->maintain(); } int kth(Node* o,int k) { if(o==NULL || k<=0 || k>o->s) return 0; int s=o->ch[0]==NULL? 0:o->ch[0]->s,w=o->w; if(s+1<=k && k<=s+w) return o->v; else if(k<=s) return kth(o->ch[0],k); else return kth(o->ch[1],k-s-w); } int rank(Node* o,int x) { if(o==NULL) return 0; int d=o->cmp(x),s=o->ch[0]==NULL?0:o->ch[0]->s; int f= d==1? s+o->w:0; if(d==-1) return s+1; else return rank(o->ch[d],x)+f; } void query1(Node* o,int x,int& ans) { if(o==NULL) return ; if(o->v<x) { ans=o->v; query1(o->ch[1],x,ans); } else query1(o->ch[0],x,ans); } void query2(Node* o,int x,int& ans) { if(o==NULL) return ; if(o->v>x) { ans=o->v; query2(o->ch[0],x,ans); } else query2(o->ch[1],x,ans); } int n,opt,x,ans; Node* root=NULL; int main() { //srand(time(0)); //bzoj上不要用 否则RE scanf("%d",&n); FOR(i,1,n) { scanf("%d%d",&opt,&x); switch(opt) { case 1: insert(root,x); break; case 2: remove(root,x); break; case 3: printf("%d\n",rank(root,x)); break; case 4: printf("%d\n",kth(root,x)); break; case 5: ans=0; query1(root,x,ans); printf("%d\n",ans); break; case 6: ans=0; query2(root,x,ans); printf("%d\n",ans); break; } } return 0; }
相关文章推荐
- 全栈工场实训13---Android---消息总线机制
- Java 基础 强引用、弱引用、软引用、虚引用
- iOS之单例类一
- PHP正则表达式语法汇总
- js验证身份证
- CSS3 垂直树状图——运用 :before 和 :after
- Python爬虫进阶一之爬虫框架Scrapy安装配置
- Html - TextArea - auto sizing to avoid scrollbar
- git的安装
- 源码推荐(12.04B):炫酷的个人中心页面(Swift版),动态瀑布流-展示网络图片
- Eclipse CDT、MingGW 遇到的一些错误汇总
- Java中的Scanner类
- android典型代码系列(十六)------GPS定位
- 在eclipse下调试jar的源码(activiti5、spring等)
- sun.misc.BASE64Encoder找不到jar包的解决方法
- DeBug调试输出
- IOS 高斯模糊 (毛玻璃效果 UIVisualEffect)
- 高并发的epoll+线程池,业务在线程池内
- java.lang.IllegalArgumentException: attempt to create saveOrUpdate event with null entity
- plsql developer调试触发器