什么是线段树?
线段树,是一种 二叉搜索树 。它将一段区间划分为若干 单位区间 ,每一个节点都储存着一个区间。它 功能强大 ,支持区间求和,区间最大值,区间修改,单点修改等操作。
线段树的每一个节点都储存着一段区间[L…R] 的信息,其中 叶子节点 L=R 。
它的大致思想是:将一段大区间平均地划分成 2 个小区间,每一个小区间都再平均分成 2个更小区间……以此类推,直到每一个区间的 L 等于 R(这样这个区间仅包含一个节点的信息,无法被划分)。通过对这些区间进行修改、查询,来实现对大区间的修改、查询。
这样一来,每一次单点修改、单点查询的时间复杂度都只为 O (logn) 。
线段树的基本结构与建树
线段树将每个长度不为1的区间划分成左右两个区间递归求解,把整个线段划分为一个树形结构,通过合并左右两区间信息来求得该区间的信息。这种数据结构可以方便的进行大部分的区间操作。
有个大小为 5 的数组 a={10,11,12,13,14},要将其转化为线段树,有以下做法:设线段树的根节点编号为 1,用数组d 来保存我们的线段树,di 用来保存线段树上编号为i 的节点的值(这里每个节点所维护的值就是这个节点所表示的区间总和)。
1.为什么要开4倍区间?
2.延迟标记:节点结构体中新增一个标记,记录这个节点是否会进行某种修改,对于任意区间的修改,我们先按照区间查询的方式将其划分成线段树中的节点,然后修改这些节点的信息,并给这些节点打上标记。在修改和查询的时候,如果我们到了一个节点 P,并且要继续查看其子节点,那么我们就要看看节点 P 是否被标记,如果有,则需要按照其标记首先修改子节点的信息,并且给子节点都打上相同的标记,同时取消节点 P 的标记,这一操作称为标记下放,也叫 pushDown
可以这么理解,假设爷爷要给两个孙女压岁钱,所以爷爷就先把总的压岁钱给自己的儿子,让儿子给女儿
,但是儿子觉得自己的女儿还太小了,暂时用不到,于是就先保存着。突然有一天爷爷准备要问孙女拿到压岁钱了没有,此时爸爸着急了,就赶紧把压岁钱给了女儿