历史版本和 笔记
一、简要介绍
维护序列
- 给出
,将 加上 。 - 记录一个版本,并复制一个新版本,以后的操作在新版本进行。
- 给出
,求 所有历史版本的和。
操作总数为
对于一个线段树节点,它的标记队列(就是将标记从前往后放入一个队列中)一定如下,其中
而对应那个时候即将下传的 tag 就是
记
也就是说,记录
每次更新时,先更新历史版本和,方法是让历史版本和加上未更新的和乘上
t[rt].sh += tc * t[rt].s + ts;
t[rt].s += tag * len;接着考虑自己的 tag
根据线段树 tag 的定义,父亲的 tag 一定是比自己的 tag 的“更新时间”要晚,故
综上:
(变量而不是结构体成员的,都是来自父亲的信息)。
t[rt].tc += tc;
t[rt].ts += tc * t[rt].tag + ts;
t[rt].tag += tag;二、刷题总结
1. P3246 [HNOI2016] 序列
解法 (1)
离线询问,对
意思就是线段树的区间
假设扫描线扫到
当扫描到
如果把扫描到的不同的
那么不固定左端点
解法 (2)
由 NOIP 2024 T4,
2. CF997E Good Subsegments
好区间换句话就是说
同理,离线询问,对
然后同上题,求答案即可,答案就是
为什么最小值就行了?易得
这题还有个牛逼的地方,很多题解都没讲:他没有加法标记。因为最小值个数由 push_up 决定,所以相当于它的标记队列全是
3. P10637 BZOJ4262 Sum
有一个经典的
解决一个就可以解决另一个。
依旧考虑对
4. P8868 [NOIP2022] 比赛
神题。
题目要求:
相当于上一题从加号变成了乘号。
考虑只算区间乘积,怎么做(
将红色的部分当作 tag,做历史版本和即可。