1. 什么是线段树


线段树,是一种二叉搜索树。它将一段区间划分为若干单位区间,每一个节点都储存着一个区间。它功能强大,支持区间求和,区间最大值,区间修改,单点修改等操作。线段树的思想和分治思想很相像。线段树的每一个节点都储存着一段区间[L…R]的信息,其中叶子节点L=R。它的大致思想是:将一段大区间平均地划分成2个小区间,每一个小区间都再平均分成2个更小区间……以此类推,直到每一个区间的L等于R(这样这个区间仅包含一个节点的信息,无法被划分)。通过对这些区间进行修改、查询,来实现对大区间的修改、查询。这样一来,每一次修改、查询的时间复杂度都只为O(log2n)O(\log_2n)O(log2n)。但是,可以用线段树维护的问题必须满足区间加法,否则是不可能将大问题划分成子问题来解决的。

2. 线段树的原理和实现


注意:如果我没有特别申明的话,这里的询问全部都是区间求和线段树主要是把一段大区间平均地划分成两段小区间进行维护,再用小区间的值来更新大区间。这样既能保证正确性,又能使时间保持在log级别(因为这棵线段树是平衡的)。也就是说,一个[L…R]的区间会被划分成[L…(L+R)/2]和[(L+R)/2+1…R]这两个小区间进行维护,直到L=R。

线段树还是没有理清楚_第1张图片

上图是一棵1-5区间的线段树。

我们发现这个线段树是一棵二叉树,每个节点表示一个区间,根节点对应区间1-n.每个叶子节点都只表示单点,针对二叉树编号的性质(二叉树的每个父亲节点f的左节点编号是2f,右节点编号是2f+1),我们可以使用一维数组实现线段树。

也就是说,我们开一个一维数组,一维数组的下标表示这棵线段树的节点编号,里面存的值表示这个节点所表示的区间中我们要维护的特性:如和、最值等。

简单线段树支持的操作


刚刚已经说过,线段树是一种博大精深的数据结构,它的功能和操作实在是太多了。之所以反复强调这些,是为了让读者清楚,在线段树的海洋中,我们都不过是探其一角罢了,千万不要妄自尊大,以为自己已经把线段树全部搞完了。

简单线段树支持单点查询,区间查询,单点修改,区间修改,我们发现这和树状数组的一些支持项目类似,但是却不完全包含,因为树状数组仅支持区间求和,且必须是1−