线段树用于解决什么问题
线段树用于解决区间更新并查询的问题,比如以下操作交替进行
- updateRange
- updatePoint
- queryRange
线段树图解
下面是对长度为 7 的数组建立的线段树,每一段管理一个区间,每一段又分成两个子区间进行管理,从图中可以看出,这样的树是一颗完全二叉树,可以使用数组+递归的方式创建。
线段树的构建
使用数组建树。
数组大小保险期间是 4n,证明方法如下:
区间查询
构建线段树的主要目的是区间查询,区间查询,比如求区间的总和、求区间最大值/最小值等操作。基本思路是将其拆分成几个不相交的区间,这些不相交的区间正好就是线段树中的节点,然后合并多个区间的值。
单点更新
单点更新的思路是从根节点出发,找到其所在的叶子节点,修改叶子节点的值,然后向上更新。这个过程可以递归表示。
区间更新
如果要求修改区间 [l,r],把所有包含在区间 [l,r] 中的节点都遍历一次、修改一次,时间复杂度无法承受。我们这里要引入一个叫做 「懒惰标记」 的东西。
每次修改,通过打标记的方式表明该节点对应的区间在某一次操作中被修改,但是不更新该节点的子节点,实质上的修改等到下一次访问带有标记的节点才进行。
在访问的时候,如果遇到带有标记的节点,那么将标记下推。
如果是要将区间修改为一个指定的值,而不是加上某一个值:
总结修改和访问的逻辑就是,如果当前区间在修改区间内,那么直接增加标记,如果不在,则看下自身有没有修改标记,有就下推,然后递归左右儿子,最后更新自身节点值。
代表题目类型
区间最大值/最小值/和
区间合并问题
区间合并,区间查询问题:
- 修改某一个区间的值。
- 查询区间为 [qleft,qright] 中满足条件的连续最长区间值。
这类问题需要在区间更新和区间查询的基础上增加变动,在进行向上更新时需要对左右子节点的区间进行合并。
扫描线问题
题目列表
02. 线段树题目 | 算法通关手册(LeetCode)