【模板】【bzoj3224】Tyvj 1728 普通平衡树 Treap
2015-11-24 13:54
441 查看
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
[code]10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598
Sample Output
[code]106465 84185 492737
HINT
1.n的数据范围:n<=1000002.每个数的数据范围:[-1e7,1e7]
Source
平衡树Treap裸题,不得不说是一个很好的裸题。
在小绿的建议下用null替代了NULL
代码:
[code]#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int SZ=10000010; const int INF=2000000000; struct node{ node *ch[2]; int r,sz,v,cnt; void maintain(); int cmp(int x) { if(x==v) return -1; return x < v? 0 : 1; } }T[SZ], *null, *root; void node :: maintain() { sz=cnt + ch[0]->sz + ch[1]->sz; } int Tcnt=0; node* newnode(int x) { node *k = T + (++ Tcnt); k->ch[0] = k-> ch[1] = null; k->r=rand(); k->v=x; k->cnt=1; k->sz=k->cnt; return k; } /*旋转*/ void rotate(node* &p,int d) { node *k=p->ch[d^1]; p->ch[d^1]=k->ch[d]; k->ch[d] = p; p->maintain(); k->maintain(); p = k; } /*插入*/ void insert(node* &p,int x) { if(p==null) { p=newnode(x); return ; } int d=p->cmp(x); if(d==-1) { (p->cnt)++; (p -> sz)++; return ; } insert(p->ch[d],x); if(p->ch[d]->r > p->r) rotate(p,d^1); p->maintain(); } /*删除*/ void erase(node* &p,int x) { if(p==null) return ; int d=p->cmp(x); if(d==-1) { if(p->cnt>1) { (p->cnt)--; (p->sz)--; return ; } if(p->ch[0]!=null && p->ch[1]!=null) { int dd = p->ch[0]->r > p->ch[1]->r ? 0 : 1; rotate(p,dd^1); erase(p->ch[dd^1],x); } else { if(p->ch[0]!=null) p=p->ch[0]; else p=p->ch[1]; } } else erase(p->ch[d],x); if(p!=null) p->maintain(); } /*查询x的排名*/ int query_rank(node *p,int x) { if(p==null) return 0; if(x==p->v) return p -> ch[0] -> sz + 1; else if(x < p->v) return query_rank(p->ch[0],x); else return p -> cnt + p -> ch[0] -> sz + query_rank(p->ch[1],x); } /*查询第k小的数*/ int query_num(node *p,int k) { if(p == null) return 0; int sz = p -> ch[0] -> sz; if(k <= sz) return query_num(p->ch[0],k); else if(k > sz + p->cnt) return query_num(p->ch[1],k - sz - p->cnt); else return p->v; } /*查询x的前驱*/ int query_pre(node *fuckdc,int x) { int ans = 0; while(fuckdc != null) { if(fuckdc -> v >= x) fuckdc = fuckdc -> ch[0]; else { ans = fuckdc -> v; fuckdc = fuckdc -> ch[1]; } } return ans; } /*查询x的后继*/ int query_suf(node *fuckdc,int x) { int ans = 0; while(fuckdc != null) { if(fuckdc -> v <= x) fuckdc = fuckdc -> ch[1]; else { ans = fuckdc -> v; fuckdc = fuckdc -> ch[0]; } } return ans; } int main() { freopen("phs.in","r",stdin); freopen("phs.out","w",stdout); null = newnode(-1000000000); null -> sz = null -> cnt = 0; null -> r = -1; root = null; int m; scanf("%d",&m); while(m--) { int opt,x; scanf("%d%d",&opt,&x); switch(opt) { case 1: insert(root,x); break; case 2: erase(root,x); break; case 3: printf("%d\n",query_rank(root,x)); break; case 4: printf("%d\n",query_num(root,x)); break; case 5: printf("%d\n",query_pre(root,x)); break; case 6: printf("%d\n",query_suf(root,x)); break; } } return 0; } /* 100 1 1 1 1 1 1 1 2 4 1 4 2 4 3 4 4 2 1 4 1 4 2 4 3 2 2 4 1 4 2 */
相关文章推荐
- 解决DatePickerDialog和TimePickerDialog控件取消按钮问题
- M1阶段事后总结
- 为什么成为一名程序员这么难?
- Java 8的八个新特性
- jQuery 1.9.1源码分析系列(十)事件系统之主动触发事件和模拟冒泡处理
- 组内会议总结(一)
- android之Widget开发详解实例一
- Object中的一些方法
- 深入理解javascript系列
- inline,block 和 inline-block 的区别
- 三分钟U极速轻松实现用U盘装Win7系统的教程你见过吗
- 设计模式 - 行为型模式 - 职责链模式
- 通达OA系统myisam转innodb引擎
- java system.out.printf()的使用方法 【转】
- hdu 1698 Just a Hook
- error LNK2019: 无法解析的外部符号_cvReleaseImage,该符号在函数_main 中被引用
- 通达OA系统myisam转innodb引擎
- Less学习笔记
- 打开exe并隐藏程序窗口
- Java中的位运算