题目传送门

平衡二叉树(Balanced Binary Tree)具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

平衡树是一种在信息竞赛中常用的数据结构,而Treap也是其中之一。说实话花了一天来屮这个Treap。

Treap简单地来说就是二叉搜索树的升级版,只不过在其基础上增加了一个rand值,并利用堆维护rand值,使二叉搜索树的rand值满足堆的性质。

从而保证Treap的高度基本为logN。

Treap的核心就是一个Rotate,它能保证Treap的性质。

插入:像二叉搜索树一样插入,在子节点不满足堆的性质时Rotate。

删除:先找到节点,如果没有儿子,直接删除。有一个儿子,直接将儿子覆盖到当前节点。有两个儿子,Rotate之后递归向下。

其他操作较简单,看code有解释。

code:

#include <cstdio>
#include <cstdlib>
#include <cstring> int read()
{
char c;while(c=getchar(),(c<''||c>'')&&c!='-');
int x=,y=;c=='-'?y=-:x=c-'';
while(c=getchar(),c>=''&&c<='')x=x*+c-'';
return x*y;
} int N,dist; struct Treap{
int tr[][],cnt,ks[],v[],tot[];
int f[],root;
Treap(){
memset(tr,,sizeof tr);
memset(ks,,sizeof ks);
memset(v,,sizeof v);
cnt=;
} void rotate(int &x,int o)//旋转
{
int k=tr[x][o];
tr[x][o]=tr[k][o^];
tr[k][o^]=x;
f[k]=f[x];//更新
f[x]=f[tr[x][]]+f[tr[x][]]+tot[x];
x=k;
} void Insert(int &x,int val)//插入节点
{
if(!x){
x=++cnt;
ks[x]=rand();
v[x]=val;
tot[x]=;//当前节点共有几个相同的值
f[x]=;
return ;
}f[x]++;//统计当前这个节点的子树共有几个节点
if(val==v[x]){tot[x]++;return ;}
int to=val>v[x];
Insert(tr[x][to],val);
if(ks[tr[x][to]]>ks[x])rotate(x,to);//不满足堆的性质,Rotate
return ;
} void Delete(int &x,int val)//删除
{
if(!x)return ;
if(val==v[x]){
if(tot[x]>){tot[x]--;f[x]--;return ;}
if(!tr[x][]&&!tr[x][]){v[x]=tot[x]=ks[x]=;x=;return ;}
if(!(tr[x][]*tr[x][])){
x=tr[x][]+tr[x][];
return ;
}
rotate(x,);
Delete(x,val);//递归向下
return ;
}
int to=val>v[x];
f[x]--;//减去总结点数
Delete(tr[x][to],val);
     f[x]=f[tr[x][0]]+f[tr[x][1]]+tot[x];
return ;
} int QueryX(int x,int val)
{
if(!x)return ;
if(v[x]==val)return f[tr[x][]]+;//小细节,可以直接return左子树总结点+1
int to=val>v[x];
return QueryX(tr[x][to],val)+(to?(f[tr[x][]]+tot[x]):);//如果是访问右子树retun之后要加上f[tr[x][0]]+tot[x]
     //查询X的排名
} int QueryK(int x,int kth)
{
if(!x)return ;
if(kth<=f[tr[x][]])return QueryK(tr[x][],kth);//在左子树
if(kth>f[tr[x][]]+tot[x])return QueryK(tr[x][],kth-(f[tr[x][]]+tot[x]));//在右子树
return v[x];//查询排名为X的数
} int pre(int x,int val)//前驱
{
if(!x)return ;
if(v[x]>=val)pre(tr[x][],val);
else{
dist=x;
pre(tr[x][],val);
}
} int bac(int x,int val)//后继
{
if(!x)return ;
if(v[x]<=val)bac(tr[x][],val);
else{
dist=x;
bac(tr[x][],val);
}
}
}T; int main()
{
int W=('Y'+'u'+'a'+'o')*('S'+'h'+'i')*('D'+'o'+'g');
srand(W);
N=read();
while(N--){
int o=read(),x=read();
switch(o){
case :T.Insert(T.root,x);break;
case :T.Delete(T.root,x);break;
case :printf("%d\n",T.QueryX(T.root,x));break;
case :printf("%d\n",T.QueryK(T.root,x));break;
case :dist=,T.pre(T.root,x),printf("%d\n",T.v[dist]);break;
case :dist=,T.bac(T.root,x),printf("%d\n",T.v[dist]);break;
}
}
}

BZOJ3224_普通平衡树_KEY的更多相关文章

  1. 【BZOJ】3224: Tyvj 1728 普通平衡树(某不科学的oj)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3224 无力吐槽,无力吐槽,无力吐槽....... bzoj竟然不能用time(0)我竟然不造!!re ...

  2. 三大平衡树(Treap + Splay + SBT)总结+模板[转]

    Treap树 核心是 利用随机数的二叉排序树的各种操作复杂度平均为O(lgn) Treap模板: #include <cstdio> #include <cstring> #i ...

  3. 可持久化Trie & 可持久化平衡树 专题练习

    [xsy1629]可持久化序列 - 可持久化平衡树 http://www.cnblogs.com/Sdchr/p/6258827.html [bzoj4260]REBXOR - Trie 事实上只是一 ...

  4. 平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】

    平衡树初阶——AVL平衡二叉查找树 一.什么是二叉树 1. 什么是树. 计算机科学里面的树本质是一个树状图.树首先是一个有向无环图,由根节点指向子结点.但是不严格的说,我们也研究无向树.所谓无向树就是 ...

  5. 三大平衡树(Treap + Splay + SBT)总结+模板[转]

    Treap树 核心是 利用随机数的二叉排序树的各种操作复杂度平均为O(lgn) Treap模板: #include <cstdio> #include <cstring> #i ...

  6. 三大平衡树(Treap + Splay + SBT)总结+模板

    Treap树 核心是 利用随机数的二叉排序树的各种操作复杂度平均为O(lgn) Treap模板: #include <cstdio> #include <cstring> #i ...

  7. BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树

    之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池 ...

  8. [数据结构-平衡树]普通 FHQ_Treap从入门到精通(注释比代码多系列)

    普通 FHQ_Treap从入门到精通(注释比代码多系列) 前提说明,作者写注释太累了,文章里的部分讲解来源于Oi-wiki,并根据代码,有部分增改.本文仅仅发布于博客园,其他地方出现本文,均是未经许可 ...

  9. [BZOJ3223]Tyvj 1729 文艺平衡树

    [BZOJ3223]Tyvj 1729 文艺平衡树 试题描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区 ...

随机推荐

  1. easyui学习笔记11—tab标签页和鼠标动作

    这篇我们看看标签页是怎么实现的,默认情况下要靠点击切换标签,也可以用鼠标切换标签选项,就是鼠标放在标签上切换. 首先看看引用的资源文件 1.资源文件 <head> <meta cha ...

  2. python功能代码块记录

    python Autopep8——按PEP8风格自动排版Python代码(参考链接) autopep8 --in-place --aggressive --aggressive test_autope ...

  3. 管理kafka

    一.主题操作使用kafka-topics.sh工具可以执行主题的大部分操作(配置变更部分已被启用并被移动到kafka-configs.sh工具中).我们可以用它创建.修改.删除和查看集群里的主题,要使 ...

  4. Django中Settings中Templates的路径设置

    ## mysite/mysite/settings.py## mysite是项目名 TEMPLATES = [ { 'BACKEND': 'django.template.backends.djang ...

  5. BZOJ1923:[SDOI2010]外星千足虫(高斯消元)

    Description Input 第一行是两个正整数 N, M. 接下来 M行,按顺序给出 Charles 这M次使用“点足机”的统计结果.每行 包含一个“01”串和一个数字,用一个空格隔开.“01 ...

  6. BZOJ1770:[USACO]lights 燈(高斯消元,DFS)

    Description 貝希和她的閨密們在她們的牛棚中玩遊戲.但是天不從人願,突然,牛棚的電源跳閘了,所有的燈都被關閉了.貝希是一個很膽小的女生,在伸手不見拇指的無盡的黑暗中,她感到驚恐,痛苦與絕望. ...

  7. thinkphp5.0调用ajax无刷新加载数据

    控制器层那边就是调数据返回,这里不再赘述,视图层页面ajax部分写法如下 function shanchu(obj) { var code = $(obj).attr("code" ...

  8. 15、SpringBoot-CRUD错误处理机制(2)

    二.如何定制错误响应 1).如何定义错误处理页面 1.1.有模板引擎的情况下:error/状态码;         [将错误页面命名为 错误状态码.html 放在模板引擎文件夹里面的error文件夹下 ...

  9. 【绝迹篇】RSA加密算法(私钥加签公钥验签)

    对于上上篇博客中我讲的一个故事,本文引用: https://www.cnblogs.com/ButterflyEffect/p/9851403.html 故事中提到的关于加密会出现,私钥加密,公钥解密 ...

  10. Git--将服务器代码更新到本地

    1. git status(查看本地分支文件信息,确保更新时不产生冲突) 2. git checkout -- [file name] (若文件有修改,可以还原到最初状态; 若文件需要更新到服务器上, ...