线段树学习笔记
结构:
-
lazy_tag:
为了方便(统一),区间修改只改tag,在pushdown时分成三步:
- 计算当前节点信息
- 下传tag
- 清空当前节点tag
另外,在查询和修改操作最前面pushdown。
pushup时也要先pushdown子节点,保证子节点信息正确
-
关于lazytag的使用:2022/3/22改
看情况。有时其实仍然是修改时保证父节点信息正确,有tag只表示下传并计算出子节点值更好。
应用:
-
加乘tag的下传计算 -> 算清楚就好了
-
区间加等差数列 -> 维护差分数组,前缀和单点查询
-
区间加平方数列 -> 高阶前缀和求
-
维护区间mex:F-little w and Discretization_牛客竞赛数据结构专题班树状数组、线段树练习题 (nowcoder.com)
叶节点维护 :数字 i 最后一次出现的位置(没出现过自然就是0)
区间维护:一段区间最左边位置的点(即叶节点的最小值)
对查询的区间离线,按 右端点 从小到大排序。
query(pos) 表示查询第一个权值小于pos的叶节点编号,
一个区间 [l,r] 的答案就是 query(q[i].l),在查询一段区间时,如果左子树权值 >= pos,就说明 l~mid 的所有值全部在 pos 之后出现了,不可能成为mex值,因此就到右边去找。否则就可以在左子树中寻找。
-
维护区间历史最大值:(带区间修改+赋值)P4314 CPU 监控 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
对于这种问题,由于我们的lazytag会在pushdown时进行修改,所以会导致难以将正确的历史最值更新到叶节点
我们不对lazytag进行合并操作,想象成 一段操作序列(队列)。每次pushdown就把整段序列添加到左右儿子的队列尾,并清空当前节点的队列。
显然这样可以根据队列的信息,计算出在哪个节点达到了最大值,即历史最值。
但同时这样是不可行的,于是我们寻找一种方法:记录(维护)一个队列的标记对当前节点的影响
即额外维护两个类似tag的信息:历史区间最大加和,历史区间最大赋值
这样的话,在pushdown中进行详细的分类讨论,就可以解决这个问题。
-
线段树合并分裂应用于区间排序问题: P2824 [HEOI2016/TJOI2016]排序