视频加载失败

ST表

440 字
2 分钟
ST表

ST 表适用于解决可重复贡献问题

可重复贡献问题

在统计时,一个元素被统计多次对结果没有影响(即对于任意的运算 optopt,存在 x opt x=xx\ opt\ x = x),常见的可重复贡献问题有:求区间最值(RMQ)、区间按位与、区间按位或、区间 gcd等.

ST 表使用倍增的思想.我们现在想要快速求序列 aa 中的区间最小值,需要维护以下数据:

  • f[j][i]:从 i 开始,长度为 2j2^j 的序列的最小值.

f 数组可以通过递推的方式预处理出来,每次计算 [i,i+2j1][i, i+2^j-1] 的最小值时,可以拆分为 [i,i+2j11][i, i+2^{j-1}-1][i+2j1,2j1][i+2^{j-1}, 2^j-1] 这两个区间中的较小值,递推关系如下:

f[j][i]=min{f[j1][i],f[j1][i+2j1]}f[j][i] = \min\{f[j-1][i], f[j-1][i+2^{j-1}]\}

显然,初始条件为:f[0][i]=a[i]f[0][i] = a[i].预处理时间复杂度 O(nlogn)O(n\log n)

for (int i = 0; i <= n; i++) {
st[0][i] = a[i];
}
for (int j = 1; j <= 17; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
st[j][i] = min(st[j - 1][i], st[j - 1][i + (1 << (j - 1))]);
}
}

在查询 [l,r][l,r] 的最小值时,我们可以将长度 sslog2\log_2.设结果为 kk,则 2k2^k 必定大于等于 ss 的一半,且小于 ss.此时,答案为从 ll 开始,长度为 2k2^k 的区间,和末尾为 rr,长度为 2k2^k 的区间的最小值.这两个区间的交集必然是 [l,r][l,r].可以列出表达式:

ans=min{f[k][l],f[k][r2k+1]}ans=\min\{f[k][l],f[k][r-2^k+1]\}

查询复杂度是 O(1)O(1) 的.

int query(int l, int r) {
int len = log2(r - l + 1);
return min(st[len][l], st[len][r - (1 << len) + 1]);
}
<< 的优先级问题

在 C++ 中, <<>> 的优先级是低于 +- 的,因此在进行左移和右移运算时,一定要注意括号问题.

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

ST表
https://blog.jerrylab.top/posts/ds/st/
作者
Jerry
发布于
2026-08-05
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Jerry
Hello, I'm Jerry.
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
最新动态
站点统计
文章
80
分类
3
标签
35
总字数
89,198
运行时长
0
最后活动
0 天前
站点信息
构建平台
Cloudflare Pages
博客版本
Firefly v6.16.5
文章许可
CC BY-NC-SA 4.0

当前页面没有目录