zoukankan      html  css  js  c++  java
  • [洛谷P3369] 【模板】普通平衡树——从BST开始说起(施工中

    [洛谷P3369] 【模板】普通平衡树

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    插入 (x)
    删除 (x) 数(若有多个相同的数,因只删除一个)
    查询 (x) 数的排名(排名定义为比当前数小的数的个数(+1))
    查询排名为 (x) 的数
    (x) 的前驱(前驱定义为小于(x),且最大的数)
    (x) 的后继(后继定义为大于(x),且最小的数)

    Input

    第一行为(n),表示操作的个数,下面(n)行每行有两个数(opt)(x)(opt)表示操作的序号((1≤opt≤6))

    Output

    对于操作 (3,4,5,6), 每行输出一个数,表示对应答案

    Example

    输入 #1

    (10)
    (1) (106465)
    (4) (1)
    (1) (317721)
    (1) (460929)
    (1) (644985)
    (1) (84185)
    (1) (89851)
    (6) (81968)
    (1) (492737)
    (5) (493598)

    输出 #1

    (106465)
    (84185)
    (492737)

    Scoring

    对于 (100%)的数据,(1≤n≤10^5)(|x|≤10^7)

    首先引入一种数据结构叫二叉排序树(又叫二叉查找树),即BST
    它有下面的性质
    (1)若左子树不空,则左子树上所有结点的值均不大于它的根结点的值;
    (2)若右子树不空,则右子树上所有结点的值均不小于它的根结点的值;
    (3)左、右子树也分别为二叉排序树;
    简单说,就是一个结点的左边都比它小,右边都比它大
    例子:

    显然,这棵树的中序遍历的输出结果就是这些结点从小到大的排序结果
    插入:

    BST可以支持以下操作:
    1.插入:小了往左走,大了往右走,走到底就新建点
    2.删除:叶子结点直接删除,否则就把右子树的最小节点换上来,再删除右子树的最小节点
    3.查询排名:所有的左边的点的个数 + 1(具体看代码)
    4.查询数值:左子树大小比要求的排名大就往左走,不然往右走
    5.求前驱:首先找到这个数,然后走到左儿子,再一直往右走到头就是了
    6.求后继:同上,走到右儿子然后一直往左走

    好了这题做完了,为什么需要Treap呢

    当插入的数是递增或者递减的时候,它就会变成这样:

    直接被卡成O(n)了

    这时候我们就要通过一种操作——旋转来维持它的平衡,也就是让它的左右子树不要相差太大

    当当当——平衡树!

    操作有两类,分别是左旋右旋
    左旋,就是把原来的右儿子放到自己的位置,自己成为它的左儿子,见图:

    右旋同理,就是左旋的镜像:

    旋转可以让平衡树变得更扁平。研究表明,在随机条件下,BST可以非常优秀,所以我们给每一个新插入的点一个随机优先级,然后根据它来旋转

    看代码:

  • 相关阅读:
    正则只能输入数字小数点后保留4位
    redis基础之安装和配置
    IDEA 2017下载及注册码
    springcloud zuul 使用zuulfilter 修改请求路径和响应头
    JPA 多表分页查询
    springboot整合JPA创建数据库表失败
    springboot整合fastjson 将null转成空字符串
    Go 结构体和map等数据结构转json字符串
    go项目找不到包问题
    设计模式--策略模式
  • 原文地址:https://www.cnblogs.com/Sheffield/p/13713182.html
Copyright © 2011-2022 走看看