朴素的treap

时间:2022-09-29 17:17:46

所谓Treap,就是一种二叉查找树,而我们知道二叉查找树,相对来说比较容易形成最坏的链表情况,所以我们有一种数据结构来防止二叉查找树出现最坏情况,那就是Treap。

Treap=tree+heap,Treap就是这样一种既是树又是堆的奇怪的东东。我们每次插入节点时,便随机的给每个节点赋给一个值,我们要求原始数据满足二叉查找树的性质,而随机值要满足堆的性质。

比如下面的一棵树:

朴素的treap

首先我们知道各个节点的“优先级”是采用随机数的方法,那么就存在一个问题,当我们插入一个节点后,优先级不满足“堆定义"的。那么我们就要旋转这课树。

①: 左左情况旋转

朴素的treap

②: 右右情况旋转

朴素的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火星人 &amp&semi; 可持久化版文艺平衡树

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

  2. BZOJ 3262&lpar;Treap&plus;树状数组)

    题面 传送门 分析 分三维考虑 对第一维,直接排序 对第二维和第三维,我们这样考虑 朴素的方法是建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&colon; &lbrack;Usaco2007 Dec&rsqb;挑剔的美食家 &lbrack;treap 贪心&rsqb;

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

  5. BZOJ 1862&colon; &lbrack;Zjoi2006&rsqb;GameZ游戏排名系统 &lbrack;treap hash&rsqb;

    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&num;编程实现

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

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

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

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

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

随机推荐

  1. 转:VC include 路径解析

    VC include 路径解析 要了解vc中使用#include命令包含头文件所搜寻的路径,必须先了解vc中的几种路径: 1. 系统路径 系统路径在vc中是"Tools->Option ...

  2. SQLite建表并添加数据

  3. SAP 默认的连接端口

    3708.3908.4008.32<instance number> 如instance number是00的话,就是3200,这是给 disp+working process 用的. 3 ...

  4. 动态改变EasyUI grid 列宽和隐藏列

    隐藏显示 $('#yourGrid').datagrid('hideColumn','yourColumn'); $('#yourGrid').datagrid('hideColumn','yourC ...

  5. Delphi 客户端调用Webservice 的TClientdataset 报出&OpenCurlyDoubleQuote;http&colon;&sol;&sol;www&period;borland&period;com&sol;namespaces&sol;Types-IAppServerSOAP”

    http://www.borland.com/namespaces/Types-IAppServerSOAP 服务器未能识别 HTTP 头 SOAPAction 的值 (2011-04-25 16:4 ...

  6. api接口json串换行

    1.问题描述:在后台输入框中明明回车换行了,但是返回到 app客户端显示出来的 确实带有 \n  这个时候无论怎么调试都不行: 2.铺垫:大家都知道 php输出字符串的时候  使用 单引号 比使用 双 ...

  7. Linux上安装 MongoDB ZK MEMCACHE PHP扩展

    安装mongo扩展: 下载地址:https://github.com/mongodb/mongo-php-driver,下载该源码包 /usr/local/php/bin/pecl install m ...

  8. js 函数 作用域 全局作用域 局部作用域 闭包

    一个变量没有声明但调用 直接报错,声明没有赋值会显示未定义. 作用域 作用域(scope):一条数据可以在哪个范围中使用. 通常来说,一段程序代码中所用到的数据并不总是有效/可用的,而限定这个数据的可 ...

  9. reset&lpar;&rpar;方法的使用、jq下面reset&lpar;&rpar;的正确使用方法

    reset()是 原生js的的方法,所有浏览器都支持,而且必须是form元素包括下的表单元素,但是JQuery中没有reset方法, 效果图:  错误用法: 正确用法: js用法: document. ...

  10. 背水一战 Windows 10 &lpar;97&rpar; - 选取器&colon; CachedFileUpdater

    [源码下载] 背水一战 Windows 10 (97) - 选取器: CachedFileUpdater 作者:webabcd 介绍背水一战 Windows 10 之 选取器 CachedFileUp ...