虽然是总结,但是真的讲不出点啥,贴个板子就溜
毕竟就我自己看
树状数组
单点修改,区间查询
1 |
|
单点修改,区间查询好像还能CDQ分治
进阶操作:区间修改,单点查询
用树状数组维护差分序列
1 | // 区间修改 |
很多时候需要配合二分,直接套上去是 \(\mathcal O(\log^2 n)\) 的。
树状数组虽然是拍扁的线段树,但是仍然保留不少好的性质,其实可以在树状数组上二分的,单次 \(\mathcal O(\log n)\)。
线段树
区间修改,区间查询
要开4倍空间
每个节点的l,r可以存下来,也可以现算(卡空间的话)
包装起来比较优美
最好动态开点(存\(lson\)和\(rson\)),当成二叉堆存也行(比较难调,还丑)
1 | struct Segtree { |
线段树基本上都套板子,会魔改的只有\(push\_up()\)和\(query()\)的合并操作
势能线段树
没有 lazy tag 的暴力修改。
区间开根
每个数开方几次就会变成1,暴力修改即可。
打tag记录区间是否都为1。
区间改成约数
同上。
线段树维护序列操作
基本上都是多了维护前缀答案和后缀答案,从而利于合并。
区间最大子段和
记录每个节点的最大子段和,最大前缀,最大后缀,区间和。
区间涂色
维护前缀空房数和后缀空房数,同上。
线段树合并
合并的是动态开点线段树。
若两棵树重合的点数为 \(m\),单次合并复杂度 \(\mathcal O(m\log n)\),所以适用于插入点数较少的情况。
注意线段树空间复杂度 \(\mathcal O(n\log n)\),\(n=10^5\) 的话开到 \(5\times 10^6\) 吧。
个人觉得还算好理解。
1 | struct SegTree { |