目录
一.What is Segment Tree?
1.概念
线段树是一种二叉搜索树,主要用于区间查询与修改,是树状数组的一种升级版。它的时间复杂度是:①建树;②查询
。先来说一说如何实践线段树。
2.实践
(1)建树
线段树中的每一个结点表示了一个区间[a,b];根节点表示的是“整体”的区间,每一个叶子节点表示了一个单位区间。
对于每一个非叶结点所表示的区间[a,b]:左儿子表示的区间为[a,(a+b)/2];右儿子表示的区间为[(a+b)/2+1,b]。
以下是一棵样例线段树:
附代码:
inline void build (int i, int l, int r){//i表示编号,l和r是左右区间端点
tree[i].l = l, tree[i].r = r;
int mid = (l + r) / 2;
if (l == r)
return ;
build (i * 2, l, mid);
build (i * 2 + 1, mid + 1, r);
}
(2)修改区间
对于修改区间,我无法给出准确的代码,但是总体思想是有的。就是找到被将被修改区间完全覆盖的区间,修改它并递归回到此区间所代表的节点的父节点。就拿上面的那个图来看,如果我要修改区间[3, 5],那么区间[3, 3]和[4, 5]将被修改。附一个样例代码(不通用),表示把区间[l, r]每一段的值修改成1:
void insert (int i, int l, int r){
if (tree[i].r < l || tree[i].l > r)//如果此区间与修改区间完全不相干,直接返回
return ;
if (tree[i].l >= l && tree[i].r <= r){//此区间被将修改区间完全覆盖
tree[i].cnt = (tree[i].r - tree[i].l + 1) * 1;//因为是每一段,所以整个区间的总值就是看这个区间的段数有多少段