亚特兰蒂斯
这里主要是对代码的解释
首先是对蓝书的简单做法的代码解释
我们把每一个节点看做比较独立的一个个体,他的cnt表示他所代表的区间是否在他本身的影响下被完全覆盖,这里不太好描述,下面举一个例子
比如三号节点(代表区间为[4,6])的cnt>0表示这一段区间在他这里已经被完全覆盖了,cnt=0表示在他这里没有被完全覆盖
那么在实际中,一个单位区间如何判断他是否被覆盖?
就看从代表这个区间的叶子节点到根节点的路径上,是否存在一个节点的cnt>0
比如[4,4]这个区间,如果1,3,6,12这四个节点中有一个cnt>0那么就代表实际中,[4,4]这个区间被覆盖了
我们先不考虑长度,先单独考虑维护区间是否被覆盖,那么在这种情况下,当修改操作为+1时,线段树被划分成的若干个节点的cnt都加上1,从每一个叶子节点往上走,显然都是符合实际情况的,如果修改操作为-1,当线段树被划分成的若干个节点中的某一个节点的cnt变为0了,他所代表的这些单位区间往上走,如果某个单位区间在实际中还被覆盖,那么他一定是被之前的某一次+1操作在路径上的另一个节点覆盖的,由于操作成对出现,这个节点的-1操作肯定比+1操作后面出现,所以这个节点的cnt一定>0,所以也就不会遗漏答案,同样的分析,也不会重复计算
我们再来考虑长度,由于线段树是从下往上维护信息的,我们不妨用最暴力的方法来维护信息,假设每次修改完了之后我们都从每个单位区间向上走,走到某一个节点时,如果当前节点的cnt=0,就向上传递其子节点的len之和,如果cnt>0就传递这个区间长度,那么由我们以上分析,如果一个单位区间被记录了,那么他一定会在某一个节点(cnt>0)的时候被计算贡献,也就不会遗漏答案(这个时候其实线段树中除了根节点外的节点的len可能不是实际中的len,但是由于我们只关心根节点,根节点的len一定是实际的len,就无所谓)
我们在修改之后可以直接模拟这个过程,在某次修改中,没有被涉及的区间显然不用管,他们已经传递好了,对于涉及的区间,如果cnt被减为了0,那么我们假设从这个区间所代表的的所有单位区间向上走,由于这个区间的子树都没有被修改,所以我们不用真的走,这个区间的两个子节点的len值就是已经走完之后的len,我们直接上传两个子节点的len即可
然后我们考虑如果硬要用lazy标记怎么做
首先我们考虑简单一点的情况,我们先不管区间长度,我们只维护
相当于就是简单的区间修改,区间查询最小值
t[p].dat表示
根据我们对lazy的理解,在任何一个时刻,某一个节点的dat可能不是真正的dat,必须要加上从这个节点到根节点的路径上所有节点的lazy值之和才是真正的dat;在修改函数或者查询函数走到某一个节点时,这个节点的dat和lazy是真实的
想一下我们的问题出现在哪里,如果我们现在要维护不为
那么我们在修改的时候,如果t[p].dat从
上文的分析也说明了我们要修改t[p].len就要先修改
所以我们必须换一个思路,我们认为t[p].len表示
显然dat是2,那么为2的长度和为3,所以len就为3
如果任意时刻任意节点的len都是真实的,那么当我们递归到
假设我们现在回溯了到
由数学归纳法,我们可以知道我们维护的操作是正确的
update 2024.5.18
其实蓝书的做法就是标记永久化,观察目前所用到的标记永久化的题目(这道题目,李超线段树,蒟蒻的数列),就会发现线段树的节点代表的都不是真实值,要么是单点查询(此时可以累积路径上所有标记的影响),要么是与根节点有关的查询
update 2024.7.30
其实我们对lazy标记的理解又更深了一层,除了叶子节点,我们可以知道任意一个节点维护的量代表什么:代表不考虑从这个节点到根节点路径上所有节点的lazy值(也就是忽略这些操作)所得到的值,这个值如果考虑了从这个节点到根节点路径上所有节点的lazy值就会变成当前最新的真实值
我们再来严格证明一下为什么蓝书的做法(指的是维护
如果两条线段之间,扫描线上某个单位线段被覆盖了,这就说明一定存在一个矩形,其左边界在扫描线左边,右边界在扫描线右端,也就是说这个单位线段扫描的这个区域,至少会被这个矩形覆盖,也就不会多统计;如果两条线段之间,扫描线上某个单位线段没被覆盖,那么这个单位线段扫描的这个区域不可能是面积并的一部分,如果是的话,肯定有一个矩阵满足其左边界在扫描线左边,右边界在扫描线右端,这个单位线段也就不会不被覆盖了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构