区间合并是一类问题的统称,种类很多,但在这篇博客中只需实现以下操作即可:
有一个01串,你有三种操作:
- 1.将[a, b]中的所有数字改成0
- 2.将[a, b]中的所有数字改成1
- 3.询问[a, b]中最长连续的1的长度是多少
前两种操作其实可以算作一个操作,重点在于如何高效地解决第三种操作。
虽说平衡树也可以解决这类问题,但是这里我们使用线段树来解决。
这是一个经典的老套路
线段树维护四个值(可以缩成三个,使用第四个是为了加强程序的可读性),分别是:
- lsum记录该区间左端点开始的最长连续的值为1区间
- rsum记录该区间右端点开始的最长连续的值为1区间
- sum记录该区间内最长连续的值为1的区间
- color形象解释就是记录区间的“颜色”,具体操作是当这个区间全部是1时color置1,全部为0时color置0,否则置-1。在pushup()的时候会用到。
接下来来讲讲具体的操作
首先是重中之重 pushup() p u s h u p ( )
这里博主有点懒,就不画图了,相信听了讲解自己脑补一下也是能搞懂的(听起来真的很简单~~)。
开始假设当前节点为 this t h i s ,其左儿子为 lc l c ,右儿子为 rc r c ,且 lc l c , rc r c 中四个值均准确无误,接下来要对 this t h i s 节点做 pushup() p u s h u p ( ) 操作。
分步骤讨论:
- 1、计算 lsum l s u m
脑补一下,当 lc l c 的 color c o l o r 为1时(也就是说左儿子结点全部由1组成),那么 lsum l s u m 就是 lc l c 的