题目传送门

平衡二叉树(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. Python切片(入门7)

    转载请标明出处: http://www.cnblogs.com/why168888/p/6407977.html 本文出自:[Edwin博客园] Python切片 1. 对list进行切片 L = r ...

  2. 记两个std接口equal_range,set_difference

    1.equal_range equal_range是C++ STL中的一种二分查找的算法,试图在已排序的[first,last)中寻找value,它返回一对迭代器i和j,其中i是在不破坏次序的前提下, ...

  3. js 对象数组删除和查找的方法

    deleteItem: function (array,item) { const index = this.array.findIndex(text => text.name === item ...

  4. POJ-1284 Primitive Roots---原根&欧拉函数

    题目链接: https://cn.vjudge.net/problem/POJ-1284 题目大意: 就是给出一个奇素数,求出他的原根的个数. 解题思路: 由于是m是奇素数,m的欧拉函数值为m - 1 ...

  5. 谁把我的表给drop了?

    今天生产上有人把几张表给DROP了,一通折腾.恢复备份导数回来数据,重建索引. 但是,我就想知道是谁给干掉了. 到你被删除表数据库中找日志吧.其它的也想不到更好办法了 USE '被删表数据库' --查 ...

  6. 关于PHP中的 serialize () 和 unserialize () 的使用(即关于PHP中的值与已存储的表示的相互转换)

    有时,我们会碰到这样的数据(字符串) a:3:{i:0;s:44:"/Uploads/images/2017-07-21/5971a9a08ad57.png";i:1;s:44:& ...

  7. Selenium应用代码(登录)

    这篇可以不看,主要是为了以后的应用代码(传参)做铺垫. import java.awt.Rectangle; import java.awt.image.BufferedImage;import ja ...

  8. 用LinkedList list实现栈的功能

    package homework; public class Dog extends Pet { String strain = "dogxx"; int love=80; pub ...

  9. 使用BSRR和BRR寄存器直接操作STM32的I/O端口

    STM32的每个GPIO端口都有两个特别的寄存器,GPIOx_BSRR和GPIOx_BRR寄存器,通过这两个寄存器可以直接对对应的GPIOx端口置'1'或置'0'. GPIOx_BSRR的高16位中每 ...

  10. 课时56.marquee标签(理解)

    这个标签是比较特殊的,不是html5中的新增标签 在W3C官方文档中找不到这个标签,也就是说不是官方推荐的标签 但是各大浏览器对这个标签的支持也非常不错,而且效果也非常不错 1.什么是marquee标 ...