所谓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的更多相关文章

  1. 无旋Treap - BZOJ1014火星人 & 可持久化版文艺平衡树

    !前置技能&概念! 二叉搜索树 一棵二叉树,对于任意子树,满足左子树中的任意节点对应元素小于根的对应元素,右子树中的任意节点对应元素大于根对应元素.换言之,就是满足中序遍历为依次访问节点对应元 ...

  2. BZOJ 3262(Treap+树状数组)

    题面 传送门 分析 分三维考虑 对第一维,直接排序 对第二维和第三维,我们这样考虑 朴素的方法是建k棵Treap,第i棵Treap里存第二维值为k的第三维数值 每次查询一组(a,b,c),只要在1~b ...

  3. fhq treap最终模板

    新学习了fhq treap,厉害了 先贴个神犇的版, from memphis /* Treap[Merge,Split] by Memphis */ #include<cstdio> # ...

  4. BZOJ 1691: [Usaco2007 Dec]挑剔的美食家 [treap 贪心]

    1691: [Usaco2007 Dec]挑剔的美食家 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 786  Solved: 391[Submit][S ...

  5. BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 [treap hash]

    1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1318  Solved: 498[Submit][ ...

  6. 非旋treap模板

    bzoj3580 非旋转treap 在大神教导下发现split一段区间时先split右边再split左边比较好写 #include <cstdio> #include <cstdli ...

  7. 朴素贝叶斯算法下的情感分析——C#编程实现

    这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Language Pr ...

  8. 朴素贝叶斯(NB)复习总结

    摘要: 1.算法概述 2.算法推导 3.算法特性及优缺点 4.注意事项 5.实现和具体例子 6.适用场合 内容: 1.算法概述 贝叶斯分类算法是统计学的一种分类方法,其分类原理就是利用贝叶斯公式根据某 ...

  9. scikit-learn 朴素贝叶斯类库使用小结

    之前在朴素贝叶斯算法原理小结这篇文章中,对朴素贝叶斯分类算法的原理做了一个总结.这里我们就从实战的角度来看朴素贝叶斯类库.重点讲述scikit-learn 朴素贝叶斯类库的使用要点和参数选择. 1. ...

随机推荐

  1. Awk,Cat,Head分析Nginx日志常用命令

    Nginx 日志分析   1.根据访问IP统计UV   awk '{print $1}'  access.log|sort | uniq -c |wc -l   2.统计访问URL统计PV   awk ...

  2. mybatis实现延迟加载多对一

    1.数据库表 CREATE TABLE `country` ( `cid` ) NOT NULL AUTO_INCREMENT COMMENT '国家id', `cname` ) COLLATE ut ...

  3. 对象存取器属性:getter和setter

    在一个对象中,操作其中的属性或方法,通常运用最多的就是读(引用)和写了,譬如说o.a,这就是一个读的操作,而o.b = 1则是一个写的操作.事实上在除ie外最新主流浏览器的实现中,任何一个对象的键值都 ...

  4. 异步编程Async/await关键字

    异步编程Async \await 关键字在各编程语言中的发展(出现)纪实. 时间 语言版本 2012.08.15 C#5.0(VS2012) 2015.09.13 Python 3.5 2016.03 ...

  5. 机器学习笔记1 - Hello World In Machine Learning

    前言 Alpha Go在16年以4:1的战绩打败了李世石,17年又以3:0的战绩战胜了中国围棋天才柯洁,这真是科技界振奋人心的进步.伴随着媒体的大量宣传,此事变成了妇孺皆知的大事件.大家又开始激烈的讨 ...

  6. ajax xmlhttp 局部显示另一个页面

    function loadXMLDoc(url) { var xmlhttp; if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera ...

  7. minicom在虚拟机(linux)安装配置过程

    1. minicom须要ncurses库的支持.否则安装会有问题. A. 下载ncurses.我选择是ncurses-5.6.tar.gz 下载地址:http://directory.fsf.org/ ...

  8. Linux定时器工具-crontab 各參数具体解释及怎样查看日志记录

    要使用crontab定时器工具,必需要启动cron服务: service cron start crontab的语法,以备日后救急.先上张超给力的图: crontab各參数说明: -e : 运行文字编 ...

  9. CI学习 CCNET Config 第一天

    CCNet的整体结构就是一个Xml文档,根元素就是cruisecontrol,具体的代码块如下所示: <cruisecontrol xmlns:cb="urn:ccnet.config ...

  10. mysql主从备份及常见问题处理

    1.mysql主从备份基本原理 mysql支持单向.异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.mysql复制基于主服务器在二进制日志中跟踪所有对数据库的更改(更新 ...