所谓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. 负载均衡之nginx

    什么是负载均衡负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求/数据[均匀]分摊到多个操作单元上执行,负载均衡的关键在于[均匀].在使用nginx负载均 ...

  2. PHP生成xml 无法识别或是无法读取或是浏览器不识别等问题

    PHP 数组转XML函数如下 [PHP] 纯文本查看 复制代码 ? 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 ...

  3. 音频传输之Jitter Buffer设计与实现

    在语音通信中Jitter Buffer(下面简称JB)是接收侧一个非常重要的模块,它是决定音质的重要因素之一.一方面它会把收到的乱序的语音包排好序放在buffer里正确的位置上,另一方面它把接收到的语 ...

  4. python3 scrapy+Crontab部署过程

    背景 最近有时间想学习下python3+scrapy,于是决定写一个小程序来练练手. 开发环境:MacOS High Sierra(10.13.1)+python3+scrapy. 开发工具:PyCh ...

  5. node.js之fs模块

    一.fs模块的mkdir函数,创建文件夹 var http = require("http"); var fs = require("fs"); var ser ...

  6. java线程池的创建使用

    利用java的多线程编程可以大大的提高系统的并发运行效率,线程越多并发执行的任务就越多,但是并不意味着效率会一直提高,相反会得到适得其反的效果. java中的多线程编程一共有三种方法: 继承Threa ...

  7. Android View动画效果—透明效果,旋转效果(二)

    一:动画效果 方法一:动画效果用AlphaAnimation类.直接加入 AlphaAnimation aa = new AlphaAnimation(0,1); //设置透明度 aa.setDura ...

  8. Linux 高速操作IOport

    在嵌入式设备中对GPIO的操作是最主要的操作. 一般的做法是写一个单独驱动程序,网上大多数的样例都是这种.事实上linux以下有一个通用的GPIO操作接口.那就是我要介绍的 "/sys/cl ...

  9. ShuffleNet总结

    在2017年末,Face++发了一篇论文ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devic ...

  10. 工厂方法模式的一些思考(java语法表示)

    同为创造型设计模式的简单工厂模式可以理解为对new关键字的代替. 本着重复三次即重构的原则,如果一个对象在不同的地方被new了两次以上,那就可以考虑使用它.那我们为什么要用简单工厂模式代替new呢?就 ...