学习笔记·对于线段树双重标记的理解

在开始这个话题之前,先简略说明一下单个lazy标记的作用与意义(想详尽了解的话自行百度一下,有很多)。

lazy标记

  • 作用:降低区间操作的复杂度
  • 意义:lazy标记表示已对当前节点进行了相应修改,而暂时没有对其左右子节点进行修改
  • 注意:一旦打了标记就要修改当前节点的值,标记只表明未修改其左右子节点,而非未修改当前节点。

双重标记

一些题有多种区间修改方式,仅用一个标记并不能很好的维护;不过,有了单个标记的思想,就可以将其拓展到多个标记了。

问题引入

多重标记中最常见的就是双重标记。每个标记的作用、意义都与单个标记时无异。当两个标记互不影响时,我们只需要按照单个标记那样一个个处理就好了,这里不再赘述。不过,当两个标记互相之间有影响时,会出现一个问题:两个标记的修改顺序是怎样的呢?以bzoj1798为例,假设线段树中的某个节点有一个区间加标记,还有一个区间乘标记,那么在修改及下放标记时,应该先加后乘,还是先乘后加呢(显然,这两种不同的操作会得到不同的解)?

思考

既然顺序不清,不妨就定义一个优先级吧!仍以上题为例:
定义同时存在两个标记时表示先乘后加。那么:

  • 对一个无标记的节点打加标记:直接打上加标记,同时更新sum值
  • 对一个无标记的节点打乘标记:直接打上乘标记,同时更新sum值
  • 对一个已有乘标记的节点打加标记:直接打上加标记,同时更新sum值,由于下放标记时先下放的是乘标记,这样做是正确的
  • 对一个已有加标记的节点打乘标记:问题出现了。如果直接打上乘标记,由于我们先下放的是乘标记,势必导致加操作和乘操作顺序混乱。那怎么办呢?其实,只要我们在打乘标记时修正一下加标记就OK了!根据乘法分配律, (+a)×b=×b+a×b ( 原 数 + a ) × b = 原 数 × b + a × b ,所以打乘标记b的同时将加标记a乘以b,这样就保证了标记正确。

总结

当涉及多重标记时,定义出标记的优先级,修改操作时用优先级高(先下放)的修正优先级低(后下放)的来保证标记的正确性。

例题

bzoj1798 [Ahoi2009]Seq 维护序列
luogu3373 【模板】线段树2
codevs4927 线段树练习5 题解

你可能感兴趣的:(~学习笔记&总结,数据结构-线段树,线段树)