线段树

前言

线段树只会保留重要的、具有“代表性”的区间,来优化区间查询。

但是,用线段树查询的区间信息,必须具有结合律...

简介

下图(有点儿粗糙,请不要介意):

sewgment-tree.bmp

黑数字代表编号,红色的区间代表节点管辖的区间,至于绿色和黄色的 X 会在后面讲。

建树

Lemma 1:线段树至多有 $O(\log N)$ 层

我们从最下面开始看。

每往上一层,区间的数量大约会减半(实际上向下取整),要把节点数量减半到 \(1\),也就需要 \(O(\log N)\) 层。

在最坏情况下,每一层都会维护整个数组。所以直接对于整个数组暴力的复杂度也会是 \(O(N \log N)\) 的。

但是,我们知道,线段树的核心,是拼,是凑啊!

Lemma 2:线段树有 $O(N)$ 个节点

每一个节点的作用其实就是把两个区间合并成一个,所以叶子节点有 \(N\) 个,非叶子节点有 \(N - 1\) 个,总共 \(2N - 1\) 个,也就是 \(O(N)\)

所以,对于叶节点,我们直接把信息传上来;对于非叶子节点,我们用其两个儿子节点的信息合并。

区间查询

Lemma 3:对于一个区间,每层至多有 $2$ 个节点所管辖的区间是这个区间的子区间,并且这个节点的父亲的区间不是这个区间的子区间(这是“终止节点”的定义)。
Lemma 3.1:对于一个终止节点,它的左/右边至少有一边的终止节点的深度比它低

反证。

如果两边的终止节点都比它高,那就违反了线段树的“二叉”的结构(无法解释这个终止节点到底“在哪儿”)。

证明了 Lemma 3.1 之后,就非常简单了:

还是反证。

如果有某一层有 \(3\) 个或更多终止节点,有两种情况:

  • 有两个终止节点相邻,这违反了终止节点的定义;

  • 没有两个终止节点相邻,这违反了 Lemma 3.1。

那怎么找终止节点?

直接搜索,搜到一个终止节点就返回。

segment-tree-query(2,6).bmp

posted @ 2024-04-02 22:25  hhc0001  阅读(2)  评论(0编辑  收藏  举报