Day6-线段树再过

DS

数据结构,维护序列/集合信息。

序列相比集合,额外需维护区间/单点相关信息。

线段树:适用于序列问题

平衡树:适用于集合问题

线段树/平衡树维护信息均满足双半群结构。

线段树

维护信息分治时的信息转移/存储。适用于算法竞赛中大部分问题。

考虑一个问题:给定一个长为 \(n\) 的序列,有 \(q\) 次操作,每次操作要么查询区间值的和,要么修改某个位置的值。

首先,按题意模拟。修改只需要 \(\Theta(1)\),而查询需要 \(\Theta(n)\),不可取。

然后可以考虑维护前缀和,查询只需 \(\Theta(n)\),但修改需要 \(\Theta(n)\),还是不行。

我们可以考虑平衡时间复杂度。如果我们把序列划分为长度为 \(B\) 的块,每次修改不但修改单点值,还要额外维护整个块的和。这样其实还是 \(\Theta(1)\) 的。而查询时,我们对于整块可以直接查询,剩余点单独维护,总时间 \(\Theta(\frac nB+B)\)。发现在 \(B=\sqrt n\) 时,查询时间最小。

再进一步,我们再把不同整块视为一个另外的序列,再次套娃分块。此时我们可以发现时间复杂度仅需 \(\Theta(\frac n{B^2}+B)\),当 \(B=n^{\frac 13}=\sqrt[3]{n}\) 时取到最小值。

我们能不能无限套娃,分块 \(k\) 层,使得复杂度降到 \(\sqrt[k]{n}\) 呢?

发现当 \(k\) 增加时,其实修改也在越来越慢,每次需要修改 \(k\) 个值。而我们要查询时,复杂度则为 \(\Theta(kB+\frac{n}{B^k})\),此时 \(k\) 以不能视为常数。当 \(k=\log_2n,B=2\) 时,修改和查询时间复杂度取到最小:\(\Theta(log_2n)\)。这就是一棵标准的线段树。

线段树

处理线段树

我们首先发现,区间个数不超过 \(2n-1\)。理由:\(n+\frac n2+\frac n4+\dots+1\le 2n-1\)。同时,它是一个完全二叉树,完全可以简单记录左儿子/右儿子位置。

这样,我们每次操作,将祖先路径的区间更新,祖先只有 \(\log\) 个。我们称将当前区间用儿子区间更新的操作为 push up

区间查询,我们查到处于询问范围内的区间就直接加上,剩余的不完全包含的区间,每层最多有两个(左边界,右边界),时间仍然是 \(\Theta(\log n)\)

区间修改

我们升级了:区间修改,区间查询。

区间修改麻烦在于:修改一个区间,也要修改这个区间所在子树的所有值。

我们引入新的概念:懒标记(lazy tag)。思想就是需要时再修改。

我们类似区间查询,但是在所在区间不但修改,而且增加懒标记,表示它的儿子需要如何修改。

我们每次修改或查询时,都需要处理当前节点的懒标记。注意,懒标记不但自己要处理,还要传给儿子区间。我们称这种下传懒标记操作叫做 push down

懒标记进阶

我们发现,在有的题中(如这道模板题),我们需要维护多个懒标记。注意,我们需要保证懒标记的个数是常数级,不然时间复杂度就要额外乘上处理懒标记的时间。这道题中,我们表示懒标记为区间和乘上 \(t_1\) 后加上 \(t_2\),可以维护所有操作。

当然,懒标记的处理也不能直接就写。还是这道题,我们应该先乘后加,才能保证值得正确。

线段树信息类型

线段树维护信息的最低要求为满足结合律、不同修改必须不互相互斥、修改的影响必须满足分配律。这种信息类型被称为双半群结构。

posted @ 2026-08-11 09:17  c_haoc  阅读(2)  评论(0)    收藏  举报