ST表
ST表(Sparse Table 稀疏表)
用处:
可以用来解决RMQ(区间最值)等可重复贡献问题[1]。
引入:
对于RMQ问题,我们通常有这几种方法处理:
-
朴素(即搜索)
-
打表
-
ST表
-
线段树
我们比较容易想到用打表的方法,也就是比较简单的dp,像这样:
定义
可是这样的空间复杂度
分析:
要求解一个区间的最值,ST表用了类似区间dp的方法。
对于每一次询问,我们可以通过
就像这样:
就是在这两段有重叠部分的区间取其中的最大值,重叠并不会影响
预处理:
首先,当区间长度为0时,区间的最值就是区间端点的值。即
然后开始类似区间dp的处理方法。
先枚举区间长度,再枚举区间端点。
这里的
代码:
for (int j = 1; j <= log2(n); j++)
for (int i = 0; i + (1 << j) - 1 < n; i++)
dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
查询:
和分析中说的一样
代码:
int query(int l, int r)
{
int j = (int)log2(r - l + 1);
return max(dp[l][j], dp[r - (1 << j) + 1][j]);
}
例题:
模板代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int log2N = 17; //这是计算得到的log2(N)
int dp[N][log2N]; //dp[i][j] 表示左端点为 i 区间长度为 2^j 的区间中的最大值,即区间[i,i+2^j-1]
int query(int l, int r)
{
int t = r - l + 1;
int j = (int)log2(t);
return max(dp[l][j], dp[r - (1 << j) + 1][j]);
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) scanf("%d", &dp[i][0]);
for (int j = 1; j <= log2(n); j++)
for (int i = 0; i + (1 << j) - 1 < n; i++)
dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
int l, r;
while (m--)
{
scanf("%d%d", &l, &r);
printf("%d\n", query(l - 1, r - 1));
}
}
可重复贡献问题
我们要查询一块区域 内的元素性质, 可以将该区域 用两块区域 来替代(这两个区域, 可以包含相同元素,但不可以 包含不属于 的元素) 即:
通过这个两个子区域的值, 可以推出 的值。
换句话说, 假如我们要求的值 函数为: (表示 这个集合里所有元素的结果)那么必须要满足:
比如: 问题、区间 、区间&
操作、区间|
操作等。 ↩︎
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App