treap树是一种平衡树,它有平衡树的性质,满足堆的性质,是二叉搜索树,但是我们需要维护他

为什么满足堆的性质?因为每个节点还有一个随机权值,按照随机权值维持这个堆(树),可以用O(logn)的复杂度维护他。树的期望深度是log n。

平衡树是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。权值:右儿子大于爸爸大于左儿子。

那么如何维护他呢?

我们来看看维护treap树的几个操作。

1.左旋右旋:

旋转是什么?看图:

把父亲和他左(右)儿子及其各子树调换(反了!)

左旋:左儿子上窜(爸爸的左儿子换成儿子的右儿子,儿子的右儿子换成爸爸)

右旋:右儿子上窜(爸爸的右儿子换成儿子的左儿子,儿子的左儿子换成爸爸)

左旋右旋看上去没有用,但是他是服务于插入和删除操作的。

代码:

void update(int cur){
sz[cur] = sz[lc[cur]] + sz[rc[cur]] + ;
} void right_rotate(int &Q){
int P = lc[Q];
lc[Q] = rc[P];
rc[P] = Q; //爸爸的左儿子换成儿子的右儿子,儿子的右儿子换成爸爸
update(Q); //更新右子树大小
update(P); //更新左子树大小
Q = P; //把Q换成P
} void left_rotate(int &Q){
int P = rc[Q];
rc[Q] = lc[P];
lc[P] = Q;
update(Q);
update(P);
Q = P;
}

2.插入

  插入就需要左旋右旋了,因为我们既维持treap其平衡树的性质,也要维持他堆的性质。

void insert(int &cur, int v){
if(!cur)
{
cur = ++cnt; //新加点的编号
V[cnt] = v; //把权值赋给它
R[cnt] = rand(); //给出点的随机权值
return;
}
if(v < V[cur]) //比较新加点与当前点的权值
{
insert(lc[cur], v); //把当前点放到他左儿子身上,递归下去
update(cur); //更新子树大小
if(R[lc[cur]] < R[cur]) //保持堆的性质
right_rotate(cur);
}
else
{
insert(rc[cur], v); //把当前点放到他左儿子身上,递归下去
update(cur); //更新子树大小
if(R[rc[cur]] < R[cur]) //保持堆的性质
left_rotate(cur);
}
}

3.删除

void del(int &cur, int v){//cur当前节点,v表示要删的点的权值
if(!cur)
return;
if(V[cur] == v)
{
if(lc[cur] && rc[cur])
{
left_rotate(cur);
del(lc[cur], v);
}
else
{
cur = lc[cur] | rc[cur];
update(cur);
return;
}
}
else if(V[cur] > v)
del(lc[cur], v);
else
del(rc[cur], v);
update(cur);
}

4.第k大,前驱,后继

这些都是递归求的。

比如前驱,如果当前点的权值小于要找的值,那么走它的右子树,直到当前点权值大于要找的值,找它的左子树,因为左子树比当前点权值小。

int find(int cur, int v)
{
if(V[cur] == v)
return ;
else if(V[cur] > v)
return find(lc[cur], v);
else
return sz[lc[cur]] + + find(rc[cur], v);
}
int pre(int cur,int v)
{
if(!cur)
return 0xefefefef;
if(v < V[cur])
return pre(lc[cur],v);
return max(V[cur],pre(rc[cur],v)); }
int post(int cur,int v)
{
if(!cur)
return 0x7fffffff;
if(v > V[cur])
return post(rc[cur],v);
return min(V[cur],post(lc[cur],v));
}

差不多就是这些……

洛谷板题:https://www.luogu.org/problemnew/show/P3369

真·浅谈treap树的更多相关文章

  1. 浅谈B+树索引的分裂优化(转)

    http://www.tamabc.com/article/85038.html 从MySQL Bug#67718浅谈B+树索引的分裂优化   原文链接:http://hedengcheng.com/ ...

  2. 浅谈oracle树状结构层级查询之start with ....connect by prior、level及order by

    浅谈oracle树状结构层级查询 oracle树状结构查询即层次递归查询,是sql语句经常用到的,在实际开发中组织结构实现及其层次化实现功能也是经常遇到的,虽然我是一个java程序开发者,我一直觉得只 ...

  3. 浅谈oracle树状结构层级查询测试数据

    浅谈oracle树状结构层级查询 oracle树状结构查询即层次递归查询,是sql语句经常用到的,在实际开发中组织结构实现及其层次化实现功能也是经常遇到的,虽然我是一个java程序开发者,我一直觉得只 ...

  4. (转)浅谈trie树

    浅谈Trie树(字典树)         Trie树(字典树) 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找作用的.查找的是啥?单词. 看以下几个题: 1.给出n个单词和m个询问,每次询问 ...

  5. 浅谈Huffman树

    所谓Huffman树,就是叶子结点带权的\(K\)叉树,假设每个叶子的权值为\(v\),到根的距离为\(dep\),那么最小化\(\sum v_i*dep_i\)就是\(Huffman\)树的拿手好戏 ...

  6. 【转】Senior Data Structure · 浅谈线段树(Segment Tree)

    本文章转自洛谷 原作者: _皎月半洒花 一.简介线段树 ps: _此处以询问区间和为例.实际上线段树可以处理很多符合结合律的操作.(比如说加法,a[1]+a[2]+a[3]+a[4]=(a[1]+a[ ...

  7. 浅谈B树

    B树即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如:    ...

  8. 浅谈 trie树 及其实现

    定义:又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构, 如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树. 核心思想:是空间换时间.利用字符串的公共前缀来降低查询时间的开 ...

  9. 浅谈Trie树(字典树)

          Trie树(字典树) 一.引入 字典是干啥的?查找字的. 字典树自然也是起查找作用的.查找的是啥?单词. 看以下几个题: 1.给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单 ...

随机推荐

  1. 【译】Building ArduPilot on Windows with waf and Bash

    原文链接:http://ardupilot.org/dev/docs/building-ardupilot-onwindows10.html 翻译水平有限,如有错误请指出! 在Windows上使用wa ...

  2. SpringBoot配置(2) slf4j&logback

    SpringBoot配置(2) slf4j&logback 一.SpringBoot的日志使用 全局常规设置(格式.路径.级别) SpringBoot能自动适配所有的日志,而且底层使用slf4 ...

  3. 学习笔记之scikit-learn

    scikit-learn: machine learning in Python — scikit-learn 0.20.0 documentation https://scikit-learn.or ...

  4. MySQL之Haproxy+Keepalived+MySQL高可用均衡负载部署 (网络摘抄)

    来源于:https://blog.csdn.net/weisong530624687/article/details/71536837?utm_source=blogxgwz3 一.安装主从MySQL ...

  5. 关于CoreData的用法

    有些同事觉得CoreData是一个看不懂,理解不清的神秘东东,其实ios的本地数据储存是一个sqlite数据库,一个简易的数据库,而这个CoreData是否支持所有储存的数据呢,显然不是的,站在我的角 ...

  6. Python直接改变实例化对象的列表属性的值 导致在flask中接口多次请求报错

    错误原理实例如下: class One(): list = [1, 2, 3] @classmethod def get_copy_list(cls): # copy一份list,这样对list的改变 ...

  7. Mac 日常使用tips

    20180725: windows标准的键盘连接了mac如何映射键盘?最大的好处是可以向后删除,还可以一键PageUP, PageDown ref: https://support.apple.com ...

  8. linux 时间和时区设置

    在linux中与时间相关的文件有 /etc/localtime /etc/timezone 其中,/etc/localtime是用来描述本机时间,而 /etc/timezone是用来描述本机所属的时区 ...

  9. python3 互译无线短信接口

    #!/usr/local/bin/python#-*- coding:utf-8 -*-import http.clientimport urllibimport random host = &quo ...

  10. JRebel 代理激活

    1.生成GUID   https://www.guidgen.com/ 例:04cfff79-8f45-481c-a858-a5b9590422e7 2.License Server 例: http: ...