ST 表
定义
ST 表是用于解决 可重复贡献问题 的数据结构。
可重复贡献问题 是指对于运算
RMQ 是英文 Range Maximum/Minimum Query 的缩写,表示区间最大(最小)值。解决 RMQ 问题有很多种方法,可以参考 RMQ 专题。
引入
题目大意:给定
考虑暴力做法。每次都对区间
显然,这个算法会超时。
ST 表
ST 表基于 倍增 思想,可以做到
基于倍增思想,我们考虑如何求出区间最大值。可以发现,如果按照一般的倍增流程,每次跳
我们发现
如果手动模拟一下,可以发现我们能使用至多两个预处理过的区间来覆盖询问区间,也就是说询问时的时间复杂度可以被降至
具体实现如下:
令
显然
根据定义式,第二维就相当于倍增的时候“跳了
以上就是预处理部分。而对于查询,可以简单实现如下:
对于每个询问
根据上面对于“可重复贡献问题”的论证,由于最大值是“可重复贡献问题”,重叠并不会对区间最大值产生影响。又因为这两个区间完全覆盖了
模板代码
C 风格模板
C++ 风格模板
注意点
-
输入输出数据一般很多,建议开启输入输出优化。
-
每次用 std::log 重新计算 log 函数值并不值得,建议进行如下的预处理:
ST 表维护其他信息
除 RMQ 以外,还有其它的“可重复贡献问题”。例如“区间按位和”、“区间按位或”、“区间 GCD”,ST 表都能高效地解决。
需要注意的是,对于“区间 GCD”,ST 表的查询复杂度并没有比线段树更优(令值域为
如果分析一下,“可重复贡献问题”一般都带有某种类似 RMQ 的成分。例如“区间按位与”就是每一位取最小值,而“区间 GCD”则是每一个质因数的指数取最小值。
总结
ST 表能较好的维护“可重复贡献”的区间信息(同时也应满足结合律),时间复杂度较低,代码量相对其他算法很小。但是,ST 表能维护的信息非常有限,不能较好地扩展,并且不支持修改操作。
练习
[USACO07JAN]平衡的阵容 Balanced Lineup
附录:ST 表求区间 GCD 的时间复杂度分析
在算法运行的时候,可能要经过
但是,在 GCD 的过程中,每一次递归(除最后一次递归之外)都会使数列中的某个数至少减半,而数列中的数最多减半的次数为
而查询部分的时间复杂度很好分析,考虑最劣情况,即每次询问都询问最劣的一对数,时间复杂度为
线段树的相应操作是预处理
这并不是一个严谨的数学论证,更为严谨的附在下方:
理解本段,可能需要具备 时间复杂度 的关于“势能分析法”的知识。
先分析预处理部分的时间复杂度:
设“待考虑数列”为在预处理 ST 表的时候当前层循环的数列。例如,第零层的数列就是原数列,第一层的数列就是第零层的数列经过一次迭代之后的数列,即 st[1..n][1]
,我们将其记为
而势能函数就定义为“待考虑数列”中所有数的累乘的以二为底的对数。即:
在一次迭代中,所花费的时间相当于迭代循环所花费的时间与 GCD 所花费的时间之和。其中,GCD 花费的时间有长有短。最短可能只有两次甚至一次递归,而最长可能有
同时,我们可以看到,
贡献者:@WenzelTian@DawnMagnet@Nathan@kenlig@Great-designer@mgt@Leo@Chrogeek@H-J-Granger@Henry-ZHR@ouuan@orzAtalod@Xeonacid@abc1763613206@Ir1d@北落师门@Siger@MingqiHuang@ShadowsEpic@hsfzLZH1
本页面最近更新:2/3/2023, 12:00:00 AM,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用