• 无旋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、指针版

  • 相关阅读:
    SpringMVC核心分发器DispatcherServlet分析[附带源码分析]
    SpringMVC异常处理机制详解[附带源码分析]
    SpringMVC重定向视图RedirectView小分析
    容器中使用iptables报错can't initialize iptables table Permission denied (you must be root)
    nohup介绍
    docker创建ceph集群
    maven单元测试设置代理
    Kubernetes服务之“运行单实例的有状态服务”
    关闭chrome浏览器的developer tools
    Kubernetes服务之StatefulSets简介
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7278770.html
Copyright © 2020-2023  润新知