线段树介绍(segment tree)

1.引入

给定一个区间\([1, n]\),希望你实现一种数据结构,支持以下操作:

1.修改\(i\)号节点的值。

2.询问区间\([i, j]\)中所有节点的和。

这不是树状数组板子

3.修改区间\([i,j]\)中所有节点的值

4.询问\(i\)号节点的值

这不还是树状数组板子

如果我要求一个数据结构,同时满足这四个要求。那树状数组就不行了。

树状数组其实也行

这时候就要引入一个比树状数组更高级的数据结构——线段树

2.简介

线段树,顾名思义,就是一棵树一颗一个节点,保存一个区间的信息的树。如图,就是一个保存\([1,10]\)的线段树。

线段树的结构

我们记\(l,r\)为节点\(k\)所保存的区间的左右端点。显然,当\(l == r\)时节点\(k\)为叶子结点。根节点保存\([1,n]\)其余节点保存区间\([l,r]\)。对于任意一个非叶子结点,他又两个儿子为\(k << 1,k << 1 | 1\),分别保存区间\([l,(l + r) >> 1]\)\([(l + r) >> 1 + 1,r]\)

首先,我们引入两个函数:

\[ls(k)=k<<1 \]

\[rs(k)=k<<1|1 \]

我们用\(sum[k]\)表示\(k\)节点对应区间的区间和。易知\(sum[k] = sum[ls(k)] + sum[rs(k)]\)

这里我们举两个例子

这样,我们就可以把一个区间长度为\(L\)的区间划分成不超过\(2\log L\)个小区间,然后对这个小区间进行操作。因此每次操作的时间复杂度为\(O(\log n)\)对于\(n\)次操作时间复杂度为\(O(n \log n)\)

预知后事如何,且听下回分解

posted @ 2020-09-13 21:33  Starry___sky  阅读(148)  评论(0编辑  收藏  举报
Live2D