• 关于log方线段树


    通常,线段树是一个log的。
    但是,有的用于解决特殊问题的线段树,是两个log的。
    这个额外的log有两种情况:

    第一种就是添加的标记比较特殊,使得pushdown时可能递归。
    通过诡异证明,使得均摊复杂度为(O(nlog^2n))

    第二种就是pushup时,需要递归到其中一个子树,这样每次pushup是(O(logn))的,总复杂度(O(nlog^2n))

    第一种

    李超线段树:用于维护凸包
    支持添加一条线段,询问某个位置的y坐标最值。
    以最大值为例:
    考虑标记永久化维护。把一条线段拆分成若干区间。
    为了保证询问的复杂度,每个区间只能维护一条线段。
    考虑如何在线段树的区间上加入一条新的线段:
    如果该区间没有线段或在此区间内,要加入的线段和这个区间的最优线段没有交点,则直接修改,不是最优的线段扔掉。
    否则,计算出交点,保留长度较大的一条,另一条下放到交点所在的儿子区间上。
    这个复杂度是(O(logn))的,因此总共是(O(nlog^2n))
    询问操作就是求出在所有包含它的区间的最优线段中找最优的。

    具体实现参考这里
    题目大多很模板。有的是放到了树上。

    Segment Tree Beats:
    又称吉司机线段树。
    支持将区间内大于(x)的数全部改为(x)。询问区间和等相关信息。
    通用思维:维护区间最大值(zd),最大值出现的次数(zs)(便于更新区间和),次大值(cd)
    分类讨论:
    (x>=zd),直接返回。
    (cd<x<zd),更新(zd=x)即可,zs不用动。同时更新区间和。
    (x<cd),递归左右子树即可。
    注意不要忘记维护延迟标记。
    对于其他操作(如区间加),正常实现即可。
    时间复杂度(O(nlog^2n))

    例题:[SNOI2020] 区间和
    区间和(x)取max,询问区间最大连续子段和。
    套路地,维护区间前缀后缀最大和,段内最大和,以及区间和。
    同时,维护它们的最小次小值以及最小值个数。
    由于每个数会逐渐变大,因此它们的长度会逐渐增加。
    维护一个数(z),表示使得前后缀长度改变所需要的最小的(x)
    由于段内最大和最终来源是子树内的前后缀最大和,因此维护的(z)要和子树中的(z)取min,从而把段内最大和的变化也考虑上。
    最后,再把这个(z)和次小值取min,按照上面的分类讨论进行即可。
    最多的变长次数是线段树区间长度之和(O(nlogn))
    每个变化最多在每个祖先节点都考虑一次。
    因此复杂度不会超过(O(nlog^2n))

    代码细节很多,考虑篇幅见此处

    第二种

    这个可以维护区间内的递增序列,即前缀最大值个数。
    也可以维护所有前缀最值之和。
    总之就是与前后缀最值相关的内容。
    建立一个函数计算某个线段树节点前面添加一个(a)后的前缀最大值个数。
    讨论左子节点的最大值(ma)
    (ma<=a),那么左子节点没有贡献,递归右面即可。
    (ma>a),那么右子节点的贡献与(a)无关,是一个确定值。这个值可以(pushup)时算出。因此只要递归左面即可。
    综上所述,每个节点维护它的最大值,以及右子节点的前缀最大值个数。
    (pushup)复杂度为(O(logn)),总复杂度(O(nlog^2n))

  • 相关阅读:
    关于Unity中资源打包
    关于Unity中的物理
    关于Unity中特殊目录
    关于Unity中脚本
    千八行
    早春游园
    西湖冬景
    七尖行
    黄山游记
    四季
  • 原文地址:https://www.cnblogs.com/lnzwz/p/14322600.html
Copyright © 2020-2023  润新知