数据结构 | ST 表
ST 表 (Sparse Table):对于可重复贡献问题,可在
可重复贡献问题:对于运算
ST 表
预处理
对于一个数列,ST 表储存的便是其二的幂次长度的每一段的计算结果。
具体点来说,如果一个数列长度为
- 长度为
的结果: - 长度为
的结果: - 长度为
的结果: - 长度为
的结果:
将区间可视化的话如下图:
对于长度为
预处理数据储存在一个二维数组
- 首先读入数列,储存到长度为
的结果内 - 然后通过上一层的结果递推本层结果。即:对于
长度的结果,使用 的结果进行计算。转移方程为( 代表具体场景的运算):
求解
由于 ST 表解决的是可重复贡献问题,那么两个有重复部分的区间的进行计算的话,并不会影响答案的正确性。
具体点来说,如果我们要求一个数列的区间
对于任意一个区间
- 记区间长度为
- 分解出来的两个区间的长度为
(相当于找到 的最大的 的幂次) - 分解出来的区间为:
和
将区间分解好后,我们就用上面预处理得到的结果直接计算出答案。
因此可以在
模板
运算为
预处理
void init()
{
for (int i = 1; i <= N; i++)
cin >> f[0][i];
for (int i = 1; i <= LOGN; i++)
for (int j = 1; j <= N - (1 << i) + 1; j++)
f[i][j] = max(f[i - 1][j], f[i - 1][j + (1 << (i - 1))]);
}
查询
int query(int l, int r)
{
int len = r - l + 1;
int pow = 0, pow2 = 1;
while (pow2 * 2 <= len)
{
pow++;
pow2 *= 2;
}
return max(f[pow][l], f[pow][r - pow2 + 1]);
}
此处每次查询都计算了一遍
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi