朴素的treap
所谓Treap,就是一种二叉查找树,而我们知道二叉查找树,相对来说比较容易形成最坏的链表情况,所以我们有一种数据结构来防止二叉查找树出现最坏情况,那就是Treap。
Treap=tree+heap,Treap就是这样一种既是树又是堆的奇怪的东东。我们每次插入节点时,便随机的给每个节点赋给一个值,我们要求原始数据满足二叉查找树的性质,而随机值要满足堆的性质。
比如下面的一棵树:
首先我们知道各个节点的“优先级”是采用随机数的方法,那么就存在一个问题,当我们插入一个节点后,优先级不满足“堆定义"的。那么我们就要旋转这课树。
①: 左左情况旋转
②: 右右情况旋转
好在我们写一个旋转函数就可以同时维护左旋和右旋了:
- void play(Treap* &rr,int d){
- Treap *k=rr->ro[d^];
- rr->ro[d^]=k->ro[d];//ro[0]是左孩子,ro[1]是右孩子
- k->ro[d]=rr;
- rr->rub();//rub()函数的作用是重新统计该子树的大小
- k->rub();//必须先rr再k,因为现在rr是k的孩子
- rr=k;
- }
那么我们就可以刷水题了:(洛谷-普通平衡树)
- #include<bits/stdc++.h>
- #define sight(c) ('0'<=c&&c<='9')
- #define RR NULL
- #define inf 1<<29
- #define random rrsbRRsb
- using namespace std;
- inline int random(){
- static int seed=;
- return seed=int(seed*48271LL%);
- }
- struct Treap{
- int key,rap,siz;
- Treap *ro[];
- Treap(int k){
- siz=;
- key=k;
- rap=random();
- ro[]=ro[]=RR;
- }
- inline void rub() {
- siz=;
- if (ro[]!=RR) siz+=ro[]->siz;
- if (ro[]!=RR) siz+=ro[]->siz;
- }
- inline int cop(int x){
- if (x==key) return -;
- return x<key?:;
- }
- };
- inline void read(int &x) {
- static char c; static int b;
- for (b=,c=getchar();!sight(c);c=getchar()) if (c=='-') b=-;
- for (x=;sight(c);c=getchar()) x=x*+c-;
- x*=b;
- }
- void play(Treap* &rr,int d){
- Treap *k=rr->ro[d^];
- rr->ro[d^]=k->ro[d];
- k->ro[d]=rr;
- rr->rub();
- k->rub();
- rr=k;
- }
- void Insert(Treap* &rr,int x){
- if (rr==RR) rr=new Treap(x);
- else {
- int d=x < rr->key?:;
- Insert(rr->ro[d],x);
- if (rr->ro[d]->rap > rr->rap)
- play(rr,d^);
- }
- rr->rub();
- }
- bool Find(Treap *p,int x){
- while(p!=RR) {
- int d=p->cop(x);
- if (d==-) return true;
- p=p->ro[d];
- }
- return false;
- }
- void Delete(Treap* &t,int x){
- int d=t->cop(x);
- if (d==-) {
- Treap *tmp=t;
- if (t->ro[]==RR) {
- t=t->ro[];
- delete tmp;
- tmp=RR;
- } else if (t->ro[]==RR) {
- t=t->ro[];
- delete tmp;
- tmp=RR;
- } else {
- int k=t->ro[]->rap<t->ro[]->rap?:;
- play(t,k);
- Delete(t->ro[k],x);
- }
- }
- else Delete(t->ro[d],x);
- if (t!=RR) t->rub();
- }
- int Kth(Treap *t,int k){
- int cm=;
- if (t->ro[]) cm=t->ro[]->siz;
- cm++;
- if (cm==k)
- return t->key;
- if (cm>k) return Kth(t->ro[],k);
- return Kth(t->ro[],k-cm);
- }
- int Rank(Treap *t,int k){
- int r;
- if (!t) return inf;
- if (t->ro[]==RR)
- r=;else r=t->ro[]->siz;
- if(k==t->key) return min(r+,Rank(t->ro[],k));
- if(k<t->key)
- return Rank(t->ro[],k);
- return r++Rank(t->ro[],k);
- }
- int Pre(Treap *t,int k){
- if (!t) return -inf;
- if (k>t->key) return max(t->key,Pre(t->ro[],k));
- return Pre(t->ro[],k);
- }
- int Sub(Treap *t,int k){
- if (!t) return inf;
- if (k<t->key) return min(t->key,Sub(t->ro[],k));
- return Sub(t->ro[],k);
- }
- int n,op,x;
- int main () {
- freopen("a.in","r",stdin);
- read(n);
- Treap* root=RR;
- while (n--) {
- read(op); read(x);
- switch(op){
- case :Insert(root,x);break;
- case :Delete(root,x);break;
- case :printf("%d\n",Rank(root,x));break;
- case :printf("%d\n",Kth(root,x));break;
- case :printf("%d\n",Pre(root,x));break;
- case :printf("%d\n",Sub(root,x));break;
- }
- // cout<<op<<endl;
- }
- return ;
- }
朴素的treap的更多相关文章
- 无旋Treap - BZOJ1014火星人 & 可持久化版文艺平衡树
!前置技能&概念! 二叉搜索树 一棵二叉树,对于任意子树,满足左子树中的任意节点对应元素小于根的对应元素,右子树中的任意节点对应元素大于根对应元素.换言之,就是满足中序遍历为依次访问节点对应元 ...
- BZOJ 3262(Treap+树状数组)
题面 传送门 分析 分三维考虑 对第一维,直接排序 对第二维和第三维,我们这样考虑 朴素的方法是建k棵Treap,第i棵Treap里存第二维值为k的第三维数值 每次查询一组(a,b,c),只要在1~b ...
- fhq treap最终模板
新学习了fhq treap,厉害了 先贴个神犇的版, from memphis /* Treap[Merge,Split] by Memphis */ #include<cstdio> # ...
- BZOJ 1691: [Usaco2007 Dec]挑剔的美食家 [treap 贪心]
1691: [Usaco2007 Dec]挑剔的美食家 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 786 Solved: 391[Submit][S ...
- BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 [treap hash]
1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1318 Solved: 498[Submit][ ...
- 非旋treap模板
bzoj3580 非旋转treap 在大神教导下发现split一段区间时先split右边再split左边比较好写 #include <cstdio> #include <cstdli ...
- 朴素贝叶斯算法下的情感分析——C#编程实现
这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Language Pr ...
- 朴素贝叶斯(NB)复习总结
摘要: 1.算法概述 2.算法推导 3.算法特性及优缺点 4.注意事项 5.实现和具体例子 6.适用场合 内容: 1.算法概述 贝叶斯分类算法是统计学的一种分类方法,其分类原理就是利用贝叶斯公式根据某 ...
- scikit-learn 朴素贝叶斯类库使用小结
之前在朴素贝叶斯算法原理小结这篇文章中,对朴素贝叶斯分类算法的原理做了一个总结.这里我们就从实战的角度来看朴素贝叶斯类库.重点讲述scikit-learn 朴素贝叶斯类库的使用要点和参数选择. 1. ...
随机推荐
- php 将pdf转成图片且将图片拼接
说明: 1.pdf转图片通过安装php扩展imagick实现. 2.由于windows扩展安装的一系列问题,建议在linux环境开发,windows大伙可以尝试安装. 3.为Centos 安装Imag ...
- linux系统下安装配置解压版的MySQL数据库
一.解压文件到当前目录 命令:tar -zxvf mysql....tar.gz 二.移动解压完成的文件夹到目标目录并更名mysql 命令:mv mysql-版本号 /usr/local/mysql ...
- 《图解Spark:核心技术与案例实战》作者经验谈
1,看您有维护博客,还利用业余时间著书,在技术输出.自我提升以及本职工作的时间利用上您有没有什么心得和大家分享?(也可以包含一些您写书的小故事.)回答:在工作之余能够写博客.著书主要对技术的坚持和热爱 ...
- 微信小程序语音与讯飞语音识别接口(Java)
项目需求,需要使用讯飞的语音识别接口,将微信小程序上传的录音文件识别成文字返回 而微信小程序上传的文件格式是silk的,而讯飞接口能识别wav 格式的文件,所以需要将小程序上传的silk文件转成wav ...
- Mysql的管理及使用
第1章 Mysql的管理 1.1 连接管理mysql mysql[options] #Linux或UNIX shell提示符(终端窗口) mysql --help #查看帮助信息 mysql --ve ...
- And【sql语句之为何用and一个字段两个值得不到表中的数据】
一.[一个表的一个字段的多个条件用and连接] 用and是查不到值的, and是多个条件同时成立, 也就是一个字段是不能同时等于两个值的. '; 二[相同两个表的两个相同字段的查询用and连接] '; ...
- x86 处理器开机顺序
无论是千万行的linux ,还是百万行的uefi ,或者百十行的app, 它都有一个主线.应用程序是main() 函数里面全部函数运行完,程序结束.这里main() 做为程序的起点,uefi 能够觉得 ...
- Android setContentView方法解析(一)
在Activity的生命周期onCreate中.我们一般都习惯性的调用setContentView(int layoutResID)方法,把布局文件载入到页面上来.以下我们就来通过源代码一步步的分析怎 ...
- Android之——ListView优化
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47209253 作为client.其最基本的任务就是最直观的和用户交互.从serve ...
- ajax接收json
l 什么是json? l Json和xml比较 l Ajax如何使用JSON l Ajax接收json响应案例 什么是json? JSON (JavaScript Object Notation) 是 ...