• 一篇打脸文


    打脸了...Splay其实有两种用法,第一个是常数奇大的平衡树

    而第二个就厉害了,Splay可以对区间进行操作

    具体是怎么个意思呢,我们来看这样一件事情

    对于一个数列,我们用Splay维护它的下标

    然后我们进行下面的Split操作

    1.将l-1旋转到根

    2.将r+1旋转到l-1的右儿子

    令a为r+1的左子树

    然后我们惊奇的发现a这棵子树表示了区间[l,r]

    然后...我们就可以对a为所欲为了

    当然要注意,l-1指的是数值,而不是点,所以我们需要借用Splay作为平衡树时的一个函数:find()来找到l-1存在哪个位置

    然后...我们就可以为所欲为啦

    1. 插入、删除:

    对于插入操作,我们可以将x转到根部,再将x+1转到x下方然后在x+1的左子树中插入新节点即可。 
    那么类似的对于删除,我们也可以先将x-1转到根部,x+1转到根下方,那么x就是x+1的左子树,直接删除即可~

    2. 询问:

    对于询问区间(x,y)的最值,只需将x-1转到根,然后将y+1转到x-1的下方,于是我们需要维护的区间就在y+1的左子树的所有点的集合里了,直接输出节点信息即可。

    3. 翻转、区间增加:

    和询问类似,先将x-1转到根,然后将y+1转到x-1的下方,然后对y+1的左子树打标记即可~,注意及时更新标记。

    4. 滚动:

    可以发现,滚动某个区间就等价于交换区间的两部分,我们设这个中点为z,那么我们的目的就是交换(x, z) 和 (z+1, y), 我们可以先将z转到根,然后将y+1转到z的下方,于是y+1的左子树就对应了区间(z+1,y)然后我们将这一段切下来,继续将x-1转到根,再将x转到x-1下方,最后将区间(z+1, y)接到x-1的左边即可。

    最后一个问题,怎么输出呢?

    注意到我们建Splay的时候,其实它的中序遍历就是原数组,我们写一个递归的print()函数就可以了...

    之前还一直以为Splay只是一个平衡树...

    真是Naive!

  • 相关阅读:
    如何轻松的从GAC文件夹拷贝dll出来
    UIManager的用法(用于改变界面风格)
    Java休眠睡眠方法
    Thread.currentThread().getContextClassLoader()与Test.class.getClassLoader()的区别
    Openfire编译命令
    Openfire插件开发
    通过Java代码打开浏览器,本地文件目录以及ftp站点
    使用Pack200压缩你的代码
    Java 创建文件与创建文件夹
    Openfire插件制作
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/7979369.html
Copyright © 2020-2023  润新知