zoukankan      html  css  js  c++  java
  • 无旋treap的区间操作实现

    最近真的不爽。。。一道维修数列就做了我1上午+下午1h+1晚上+晚上1h+上午2h。。。

    一道不错的自虐题。。。

    由于这一片主要讲思想,代码我放这里

    不会无旋treap的童鞋可以进这里

    呵呵。。。

    下面来切开这道题

    1、建立一个treap

    肯定不能做n次merge吧。。。虽然我看见有人这样写过了,但我毕竟自带巨大常数

    这里可以这么做

    用一个栈来维护新建treap最右边的一条链(右下角是栈顶),从左到右依次加点,每次只需将这个点的rand与栈顶的rand比较一下,如果栈顶的rand比要加的当前点的rand大,就一直退栈(小根堆),然后把这个点设为栈顶的右儿子,把最后一次退栈的的点设为当前点的左儿子。(当前点即为要加的点)

    入栈完成后,将所有点退栈。最后一次退栈的即为根。

    每个点退栈前要reset(其他文章的updata)

    然后就建好了一个treap。。。

    2、插入操作

    很容易。。。merge n次,肯定是对的,但不保证不会T。。。

    这和建树差不多。。。所以可以先建一棵树,然后与原树合并

    3、删除操作

    额,和单点差不多,把要删除部分分离出来再merge剩下部分。。。

    4、修改操作

    像线段树一样维护一个标记,当要修改(即merge或split)时更新数值并下传标记

    5、翻转操作

    像线段树一样维护一个标记,当要修改时交换左右儿子并下传标记

    6、求和操作

    每个节点维护一个sum,每次更新时更新sum,sum=data+ls.data+rs.data

    7、求最大子序列操作

    有点麻烦。。。不过还是可以做

    每个点维护三个:最大前缀,最大后缀,和最大子序列

    转移方程:

    lmax=max(ls.lmax,ls.sum+data+max(rs.lmax,0))
    rmax=max(rs.rmax,rs.sum+data+max(ls.lmax,0))

    maxx=max(ls.maxx,r.maxx,data+max(ls.maxx,0)+max(rs.maxx,0))

    这个转移方程正确性显而易见。

    还有就是修改操作时,要修改这个标记,如果修改的数是正数,修改成size*data,否则修改成data(必须选一个。。。)

    还有反转时交换lmax,rmax

    8、关于空间

    我是非指针党,空间肯定炸,所以我弄了个栈,里面装没用的空间,当建树时弹栈再用。。。当删除时回收,全部重新入栈

    然后就解决了这道题。

    补充:

    1、updata时必须先让左右儿子下传标记

    2、随机数不能重复!!!

    3、指针版

  • 相关阅读:
    jmeter工具应用1
    django1
    5.自动化测试模型
    4.清除cookie操作
    2.操作浏览器
    3.8种元素定位
    1.介绍与环境安装
    模块
    urllib库
    自动化测试PO模式
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7278770.html
Copyright © 2011-2022 走看看