题意:维护一个序列,5个操作:
1、区间加x
2、区间减x后对0取max
3、区间覆盖成x
4、询问单点值
5、询问单点历史最大值
又是一眼线段树。但是同样也有新东西。
首先,区间减x后对0取max这个操作看起来十分的棘手。还有就是历史最大值。
但是这道题的好处是单点查询,也就是说我们的每个节点并不需要维护实际信息,而只需要维护lazy-tag。将初始信息记录在叶节点tag上,在询问单点时,将一路上的tag给pushdown下去,最后一个点的tag上的值就用来更新答案了。
我们定义节点tag为一个二元组$(a, b)$ 代表执行这个标记时,对于区间内的数,先加上a然后对b取max。
那么操作1 2 3分别对应标记$(x, {- \infty})$ $(-x, 0)$ $({- \infty}, x)$
如何pushdown这个标记?设下传的标记为$(A, B)$,直接将当前标记$(a, b)$更新为即可。
在实际应用中由于数字可能爆-INF的下界,所以左边要对-INF取个max。
如何维护历史标记?同样用一个二元组$(c, d)$,分别代表该节点在上次与这次pushdown之间的最大add值和最大取max值。pushdown的话,设下传的标记为$(C, D)$,当前历史标记更新为:
左侧同样要对-INF取max。注意到更新标记涉及到节点当前标记$(a, b)$,所以pushdown时先下传历史标记再下传当前标记。
最后pushdown到叶子时,节点的$\max(a, b)$、$\max(c, d)$就分别为当前和历史的答案。