这次我们来讲一讲Treap(splay以后再更)

平衡树是一种排序二叉树(或二叉搜索树),所以排序二叉树可以迅速地判断两个值的大小,当然操作肯定不止那么多(不然我们还学什么)。

而平衡树在排序二叉树的基础上主要是增加了一个优化:就是高度较为平衡,并可以动态平衡。

而今天要讲的treap就是一种动态平衡的方法。

首先说声抱歉,因为没有那么多的时间,所以无法把左旋和右旋两种操作具体的讲,但是可以看刘汝佳的蓝书,讲得还是挺清楚的。

现在开始。

treap用的是一种比较玄学的方法,就是将每一个点还附上一个随机值,然后按照堆的性质,不管大小根堆都是一样的,所以我们每加入一个值,就利用上浮操作进行旋转,保持堆的性质,且不改变排序二叉树的性质。

操作很好理解,就是每次insert时进行判断就行了,若不满足,则上浮。

具体的排序二叉树的操作,我就不再赘述了,如果要学,可以看刘汝佳的蓝书(感觉在跟刘汝佳打广告)。

下面送上代码。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
using namespace std;
int n,root,size,ans;
struct P{
int l,r,sz,key,rd,re;//re为重复次数,key为加入权值
}t[];
void update(int k)
{
t[k].sz=t[t[k].l].sz+t[t[k].r].sz+t[k].re;
}
void left(int &k)//右旋
{
int y=t[k].r;
t[k].r=t[y].l;
t[y].l=k;
t[y].sz=t[k].sz;
update(k);
k=y;
}
void right(int &k)//左旋
{
int y=t[k].l;
t[k].l=t[y].r;
t[y].r=k;
t[y].sz=t[k].sz;
update(k);
k=y;
}
void init(int &k,int x)//加入操作
{
if(k==)
{
size++;
k=size;
t[k].sz=;
t[k].re=;
t[k].key=x;
t[k].rd=rand();
return;
}
t[k].sz++;
if(t[k].key==x) t[k].re++;
else{
if(x>t[k].key)
{
init(t[k].r,x);
if(t[t[k].r].rd<t[k].rd) left(k);//这里和下面都是判断是不是满足堆的性质
}
if(x<t[k].key)
{
init(t[k].l,x);
if(t[t[k].l].rd<t[k].rd) right(k);
}
}
}
void del(int &k,int x)
{
if(k==) return;
if(t[k].key==x)
{
if(t[k].re>)
{
t[k].re--;
t[k].sz--;
return;
}
if(t[k].l*t[k].r==) k=t[k].l+t[k].r;//k代表指针的移动,所以移动到了左或右儿子
else
{
if(t[t[k].l].rd<t[t[k].r].rd){
right(k);
del(k,x);
}
else{
left(k);
del(k,x);
}
}
}
else{
if(x>t[k].key)
{
t[k].sz--;
del(t[k].r,x);
}
else{
t[k].sz--;
del(t[k].l,x);
}
}
}
int rank1(int k,int x)//找x的排名
{
if(k==) return ;
if(t[k].key==x) return t[t[k].l].sz+;
if(x>t[k].key) return t[t[k].l].sz+rank1(t[k].r,x)+t[k].re;
if(x<=t[k].key) return rank1(t[k].l,x);
}
int rank2(int k,int x)//找排名为x的数
{
if(k==) return ;
else if(x<=t[t[k].l].sz) return rank2(t[k].l,x);
else if(x>t[t[k].l].sz+t[k].re) return rank2(t[k].r,x-t[t[k].l].sz-t[k].re);
else return t[k].key;
}
void pre(int k,int x)//找前驱
{
if(k==) return;
if(t[k].key<x)
{
ans=k;
pre(t[k].r,x);
}
else pre(t[k].l,x);
}
void nxt(int k,int x)//找后继
{
if(k==) return;
if(t[k].key>x)
{
ans=k;
nxt(t[k].l,x);
}
else nxt(t[k].r,x);
}
int main()
{
srand(time());
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int num,x;
scanf("%d%d",&num,&x);
if(num==) init(root,x);
if(num==) del(root,x);
if(num==) printf("%d\n",rank1(root,x));
if(num==) printf("%d\n",rank2(root,x));
if(num==)
{
pre(root,x);
printf("%d\n",t[ans].key);
}
if(num==)
{
nxt(root,x);
printf("%d\n",t[ans].key);
}
}
return ;
}

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

谢谢大家的观看。

如有不妥之处,请大家指出。

平衡树Treap模板与原理的更多相关文章

  1. [luogu3369]普通平衡树(treap模板)

    解题关键:treap模板保存. #include<cstdio> #include<cstring> #include<algorithm> #include< ...

  2. 算法模板——平衡树Treap 2

    实现功能:同平衡树Treap 1(BZOJ3224 / tyvj1728) 这次的模板有了不少的改进,显然更加美观了,几乎每个部分都有了不少简化,尤其是删除部分,这个参照了hzwer神犇的写法,在此鸣 ...

  3. luoguP3369[模板]普通平衡树(Treap/SBT) 题解

    链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...

  4. 洛谷 P3369 【模板】普通平衡树 (Treap)

    题目链接:P3369 [模板]普通平衡树 题意 构造一种数据结构满足给出的 6 种操作. 思路 平衡树 平衡树的模板题. 先学习了一下 Treap. Treap 在插入结点时给该结点随机生成一个额外的 ...

  5. BZOJ 3224 - 普通平衡树 - [Treap][Splay]

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中 ...

  6. 普通平衡树Treap(含旋转)学习笔记

    浅谈普通平衡树Treap 平衡树,Treap=Tree+heap这是一个很形象的东西 我们要维护一棵树,它满足堆的性质和二叉查找树的性质(BST),这样的二叉树我们叫做平衡树 并且平衡树它的结构是接近 ...

  7. 2021.12.06 平衡树——Treap

    2021.12.06 平衡树--Treap https://www.luogu.com.cn/blog/HOJQVFNA/qian-xi-treap-ping-heng-shu 1.二叉搜索树 1.1 ...

  8. hiho #1325 : 平衡树·Treap

    #1325 : 平衡树·Treap 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说的是哪两个啊? ...

  9. 写一个迷你版Smarty模板引擎,对认识模板引擎原理非常好(附代码)

    前些时间在看创智博客韩顺平的Smarty模板引擎教程,再结合自己跟李炎恢第二季开发中CMS系统写的tpl模板引擎.今天就写一个迷你版的Smarty引擎,虽然说我并没有深入分析过Smarty的源码,但是 ...

随机推荐

  1. 》》vue

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  2. HDOJ--4893--Wow! Such Sequence!【线段树+单点、区间更新】

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:给你一个长度n的数列,初始都为0.有三种操作,第一种给第k个位置的数加d.另外一种是查询区间 ...

  3. Ubuntu1204 vim中文乱码解决方法

    加入中文字符编码 sudo vi /var/lib/locales/supported.d/local #加入以下的中文字符集 zh_CN.GBK GBK zh_CN.GB2312 GB2312 zh ...

  4. eclipse中JDK、struts2、Spring、Hibernate源码查看

    一般,我们导入的只有jar文件,所以看不到对于的java文件,如果需要看源码,必须下载对应开源包的源码,一般都是zip文件,比如Spring,下载spring-framework-2.0.8-with ...

  5. Ubuntu 下 libgps 库的使用

    简介 一般 GPS 接收器会遵循美国国家海洋电子协会(National Marine Electronics Association)所指定的标准规格,其中包含传输资料的格式以及传输资料的通讯协议.那 ...

  6. 翻译:CREATE DATABASE语句

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  7. 关于SQLALCHEMY之(一)

    SQLALCHEMY是一个不可靠的方案.对于初级开发者而言,并不如SQL语句来得简明. 或者说,我不知道是不是所有的ORM数据库对象映射方案都存在这么一种情况.纯以开发逻辑而言.下述两段代码的结论是一 ...

  8. How to use GitHub with Android Studio

    转载于:http://www.wfuyu.com/technology/22499.html 目前业界主流的版本管理工具主要是 svn/git.svn是1种集中式的代码管理工具,而git是1种散布式的 ...

  9. 【java】多线程同步死锁

    package 多线程; class A{ public synchronized void say(B b){ System.out.println("A说:你把你的本给我,我把我的笔给你 ...

  10. 【python】函数说明文档