线段树深入——普适性の思路
Dans les mathématiques, le progrès vient souvent d'une abstraction plus profonde, plutôt que d'un calcul plus compliqué
— Alexandre Grothendieck
线段树深入——普适性の思路
0. 导引
前置知识:群的定义,环的定义 + 线段树(只用到动态开点?)
其实这只是一总结性的文章;
其实现在精神状态十分美好
某些奇奇怪怪的东西会用 『』
无关紧要的定义会用引用
写在 『期末』 之前
1. 朴素线段树の本质
1.1 半群
在做了这么多的线段树的题之后,对于线段树能够维护的信息,我们都有了一个判断:
- 运算需要满足结合律。e.g. 定义在 \(\Z\) 上的加法 \(+\),有 \(\forall a,b,c \in \Z, a+b+c=a+(b+c)\)
- 封闭性。(这点应该很显然了)
很好
看到这个,你有没有想到一些东西 (如果没想到,先去补习群
没错就是『半群』
__半群__
半群是一个二元组 \((G,\otimes)\)
- \(G \not= \varnothing\)
- \(\otimes\) 是定义在 \(G\) 上的运算 (封闭性)
- \(\otimes\) 满足结合律,即 \(\forall a,b,c \in G, \ a\otimes b\otimes c=a\otimes(b\otimes c)\)
1.2 本质
所以说朴素线段树就是一个基于半群的数据结构,可以叫做『半群线段树』
半群线段树
半群线段树是一个数据结构,维护一个序列 \(\{a_n\}, a_i\in G,i=1,2,3...,n\),\((G,\otimes)\) 是一个半群
支持以下操作:
- 修改,给定下标 \(\text{id},1\le\text{id}\le n\),修改值 \(d \in G\),使 \(a_\text{id}\larr d\)。
- 查询(区间查询),给定范围 \(\text l,\text r(1\le \text l \le \text r \le n)\),求 \(\otimes_{i=\text l}^{\text r}a_i\)。
这样子,对于节点 id ,它的维护就是
就是我们写的 pushup
注意:
-
对于初学者(抽象代数),应注意在半群上,运算没有交换律
-
加上
lazy_tag后,实质就并不是半群线段树了,可以说是『双半群结构』,也可以说是『环线段树』
1.3 例题(或者说应用?)
区间求和、积
实数与加法、乘法肯定构成群
矩阵乘法
矩阵与矩阵乘法是构成群的
字符串 Hash
这玩意儿之前周考考过;
乍一看,这东西好像不满足结合律,可是再仔细看看呢
先看计算过程:
不妨让 \(G\) 中的每一个元素为一个二元组 \((h,length)\),\(h\) 是字符串 Hash 值,\(length\) 是字符串长度
\(\to\) \(\otimes\) 的定义不就出来了吗
封闭性显然
$ (s_1.h \cdot \text{base}^{s_2.length} + s_2.h)\ \text{mod}\ p \ \in \ \Z_p$
\(s_1.length+s_2.length \ \in \ \N\)
结合律大家可以自己推推
1.4 信息设计~~
依然是从半群入手
本质上,就是一个『映射』(函数):\(f : ([1,n] \cap \mathbb Z)^2 \to G\)
哎呀,说简单点就是 \(f(x, y) \to G,x,y\in [1,n],\mathbb Z\)
诶,我们又知道了:\(G \otimes G \to G\)。此时有了 \(f(l,\text{mid}) = x,f(\text{mid} +1, r) = y\) ,就有:\(f(l,r)=x \otimes y\)
具体的参考大佬博客
此时由于封闭性与结合律的限制,每个区间就唯一对应了一个值,且不会在维护时丢失信息
1.5 例题
不想写了
2. 环线段树,或者 双半群?
2.1 出来了
澄清一点,此环非彼环
其实这里的环是抽象代数里的概念
__环__
环:直接用大佬的定义了
环公理 ring axioms
(1) 集合 \(R\) 称为 环,若定义了满足以下公理的二元运算 \(+, \times\),称为加法和乘法:
(i) \((R, +)\) 是 阿贝尔群。
(ii) \(\times\) 满足 结合律。
(iii) \(R\) 满足 分配律:对任意 \(a, b, c\in R\),\((a + b) \times c = a \times c + b \times c\)。
(2) 若乘法交换,则 \(R\) 称为 交换环 commutative ring。
(3) 若存在 \(1\in R\) 满足对任意 \(a\in R\),\(1\times a = a\times 1 = a\),则称 \(1\) 有 单位元。
乘法符号一般省略。加法群的单位元记为 \(0\),逆元记为 \(-a\)。
其实吧,也可以说成是 双半群 结构(信息一个半群,lazy_tag 一个半群)
环线段树是一个数据结构,维护序列 \(\{a_n\},a_i\in R,i=1,2,3...,n\),支持操作:
-
修改(区间),给定范围 \(\text l, \text r\),以及修改值 \(d\),使 \(\forall i \in[\text l,\text r],a_i \larr d \times a_i\)。
-
查询(区间),给定范围 \(\text l, \text r\),求 \(\sum_{i=\text l}^{\text r}a_i\)
这,就是一个带
lazy_tag的线段树
2.1 油水分离,如何将值与标记分开
注意:一般题目中有多少个修改操作,就有多少个 tag
规定:
-
将值记为
val -
将标记记为
tag -
将值的集合记为 \(D\)
-
将标记集合记为 \(T\)
有以下运算需得到满足:
-
\(\times : T \oplus D \to D\),给某个值加上标记
-
\(\times : T \oplus T\to T\) ,标记的下传, \(\iff\)
pushdown -
\(+:D\oplus D \to D\),值的求和
然后呢,我们发现 \(D\) 总是多维向量的集合,\(T\) 总是方阵的集合(大小:若 \(D\) 是 \(n\) 向量集合,则每个方阵大小为 \(n\times n\))
2.3 依旧应用
区间加乘+区间求和
加与乘都是线性变换,就维护向量 \([a_i,1]\),修改就乘上一个 \(2\) 阶方阵
·······(实力有限,憋不出来了)
2.4 忘了
有一篇比较好的讲区间历史操作,从矩阵乘法到标记的文章
3. 特殊的线段树
先鸽着,因为我不会
4.后记
这是我想对我们班同学说的
在学到线段树的时候,我就开始疑惑,线段树的本质是什么
再找了几篇博客后,已经有了些初步理解
也写了篇纸质版总结
我个人认为在彻底理解到这『普适性の思路』后,解决这类题的思路就有了一个固定、可靠的『路径(Path)』,虽然我还很弱
参考资料:
《抽象代数》学习笔记 I —— 群论 - qAlex_Weiq - 博客园
《抽象代数》学习笔记 II —— 环论 - qAlex_Weiq - 博客园
线段树进阶 Part 1 - qAlex_Weiq - 博客园
"Wir müssen wissen, wir werden wissen."
——大卫・希尔伯特

浙公网安备 33010602011771号