开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」第10天,点击查看活动详情
线段树的定义
将一段线性的区间(线段)分成许多的子区间,每个子区间都对应着线段树中的一个结点。
这种 结点是一段区间的数据结构就叫做线段树
线段树的建立
我们线段树的根节点代表着整条线段的结点,
倘若线段树根节点代表的线段是[1,16],则线段左边界L=1,右边界R=16;
我们分割左右边界是先算出中间值:;(遵循C/C++整形除法的向下取整)
即左孩子代表区间为:
[1,
] ------>
[1 , 8]
右孩子代表区间为 :[, 16]------> [9 , 16]
对于每个结点,我们将它代表的区间(线段)平均的分为两个小区间,从而建立左右孩子,以此类推
区间会越分越小,直到分出来的子区间L==R,长度为1,这时候便无法再分
线段树的强大功能
线段树功能强大,是算法竞赛中在特定情况下可以大幅减少时间复杂度的数据结构
它支持区间求和,区间最大值,区间公约数,区间修改,单点修改等操作,
正是因为它每次搜索都会将每段区间平分为2的性质,单点修改与查询的时间复杂度可以优化到O(log2n)
但是,线段树也不是万能的,有且仅当可以用线段树维护的问题满足区间加法
否则,将无法把每个大问题分为小问题来解决
线段树可以维护的数据类型
上文讲到,线段树只支持解决区间加法问题。那么,何为区间加法?
满足区间加法的问题,当前仅当
对于 区间的结果可以由区间
和区间
,
的结果合并而来.
即可以将一段区间上的问题,任意地分割为两个小区间来解决,原则上无需平分,最小的区间长度为1
简单的经典区间加法问题
- 区间求和
- 区间最大值
注:不满足区间加法的问题有:
- 区间的众数;
- 区间的最长不下降子序列。