一、什么是线段树?

1、线段树是一棵二叉树,树中的每一个结点表示了一个区间[a,b]。
2、每一个叶子节点表示的是一个单位区间。
3、根节点表示的是“整体”的区间。
4、对于每一个非叶结点所表示的区间[a,b]:
左儿子表示的区间为[a,(a+b)/2]
右儿子表示的区间为[(a+b)/2+1,b]


二、线段树有什么用?

线段树主要用于处理一些关于区间映射的问题。

我们需要经常处理可以映射在一个坐标轴上的一些固定线段。

由于线段是可以互相覆盖的,有时需要动态地合并线段,例如取得并区间的总长度,或者并区间的个数等等。

一个线段是对应于一个区间的,因此线段树也可以叫做区间树。


三、线段树的结构

如图:(每一个节点表示一个区间)


也可以这样表示:


我们现在知道了线段树的结构,那应该怎么定义一棵线段树呢?

很简单,可以直接定义一个结构体数组:

struct node{

    int l,r;//可以在结构体里面增加一些需要的变量。
}tree[maxn];

线段树的每个节点上往往都增加了一些其他的域。

在这些域中保存了某种动态维护的信息,视不同情况而定。

这些域使得线段树具有极大的灵活性,可以适应不同的需求。


四、线段树的表示方法

其实线段树的表示方法跟完全二叉树的表示方法是一样的,只不过完全二叉树的节点是满的,两个节点之间没有空节点,线段树的两个节点之间可能存在空节点,所以线段树比较耗空间,一般空间都要开到4n左右。


当然,线段树也可以用动态数据结构来表示(比如说指针),但是写起来比较麻烦,而且容易写错,所以一般都用完全二叉树的方法来表示。