线段树讲义||寒假
线段树介绍
- 线段树是一棵二叉树,每个节点维护一个区间内$[l,r]$的信息
- 左子树区间维护$[l,\lfloor \frac{l+r}{2} \rfloor]$的信息,右子树维护$[\lfloor \frac{l+r}{2} \rfloor+1,r]$的信息
- 节点信息可以由两个子节点合并得到
- 任意一个区间会被分为线段树上$O(\log n)$个节点
线段树可以在$O(\log N)$的时间复杂度内实现单点修改、区间修改、**区间查询(区间求和/区间最大值/区间最小值)**等操作。
线段树一般解决类似这样的问题:
已知一个数列,你需要进行下面几种操作:
- 将某区间每一个数加上 $k$。(修改)
- 求出某区间每一个数的和。(查询)
- 将某区间的每个数修改为$x$。(修改)
- 求某区间的最大值/最小值。(查询)
建树
实现
递归实现
|
|
查询&修改&求值
区间查询
进行区间查询的时候,区间和节点区间的关系有三种可能:
- 当前要查询的区间与正在询问的区间没有交集,返回空
- 当前要查询的区间被某个节点的区间完全包含,直接取该点记录的值
- 当前要查询的区间被某个节点部分包含,则将这个节点往下传递一层,直到符合上面两种情况
实现
|
|
区间修改(懒标记)
区间修改和区间查询的思路是一样的,判断当前节点区间与被修改的区间的关系,对其数据进行修改。
假如我们在修改区间$[l,r]$时,把所有与$[l,r]$有交集的节点都遍历并修改一边,时间复杂度将过高,所以我们引入懒标记。
思考:
当我们要修改$[l,r]$,有一个节点(或者是一些节点的并集)恰好是$[l,r]$,我们选择节点数最少的那个集合进行修改,并对这些集合进行标记,只有当某次访问需要这些节点的子节点时,才把变化传递下去,这样可以大大减少对更深处的节点的修改次数,降低时间复杂度。
实现
|
|
相应的,引入懒区间之后,我们在区间查询的时候要考虑懒标记是否下达,如果没有下达则要将懒标记传递下去。
|
|
例题指路:
区间求和:P3372 【模板】线段树 1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
参考
|
|
思考
相似的,如果是将某个区间内的值都修改为某个值,应该如何操作?
例题1(两种懒标记)
P3373 【模板】线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
操作 1: 格式:
1 x y k
含义:将区间$[x,y]$内每个数乘上k操作 2: 格式:
2 x y k
含义:将区间$[x,y]$ 内每个数加上k操作 3: 格式:
3 x y
含义:输出区间 $[x,y]$ 内每个数的和对m取模所得的结果这题需要考虑两种修改值的操作之间的相互影响。
- 每次对节点加/乘之前,要判断是否需要将当前节点的两种懒标记向下传递
- 判断时应该先乘后加
参考
|
|
动态开点
一般来说,线段树处理的范围在$[1,n]$,$n$一般是$1e5$的大小。
如果我们想处理负数的范围,或者是$n$达到$1e9$的数量级时,我们就需要可以动态开点的线段树。
线段树我们一般开到$4n$的大小是充足的,为了节省空间以及直接建立全树的时间,我们也可以对线段树动态开点,也就是只有当我们需要用到某些节点的时候,才去创造它。
比如,我们已经一个节点表示$[11,16]$的相关数据,我们需要修改$[13,15]$上的信息,我们就创造$[11,13]$和$[14,16]$的节点,并继续递归创建节点,直到这个线段树可以完全表示到已被修改的信息。
实现
|
|
线段树合并与分裂
线段树合并
线段树合并通过递归实现,需要有合并操作的线段树需要使用动态开点的技巧。
将线段树a和b合并,从1号点开始递归,若递归到某个节点为空,直接返回另一个树上的对应节点;若递归到叶子节点,我们合并两棵树上的对应节点。
|
|
模板题:[P4556 Vani有约会] 雨天的尾巴 /【模板】线段树合并 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
线段树分裂
线段树分裂是线段树合并的逆过程。
线段树分裂只适用于有序的序列,无序的序列是没有意义的,常用在动态开点的权值线段树上。
当分裂和合并都存在时,要注意回收节点,以免分裂时会出现节点重复/占用的问题。
- 当$[s,t]$与$[l,r]$有交集时开新节点
- 当$[s,t]$包含于$[l,r]$时,直接将当前节点接到新的树下面,把旧边断开。
|
|
模板题:P5494 【模板】线段树分裂 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
练习题一览
一些模板题/测测你的板子(!
P3372 【模板】线段树 1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
P3373 【模板】线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
[P4556 Vani有约会] 雨天的尾巴 /【模板】线段树合并 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
P5494 【模板】线段树分裂 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
[P4097 【模板】李超线段树 / HEOI2013] Segment - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)