st表:
作者:王清楚
链接:https://ac.nowcoder.com/discuss/395376
来源:牛客网
ST 表(Sparse Table)实际上是一种动态规划的方法,或者说简单一点,是用统计的思想来解决问题,它主要用于求解区间最大/最下值问题(也可也用来求和或者其他的东西)。以求区间最大值为例,它的基本思想是:用 {f[i] [j]}f[i][j]维护从从i开始长度为 2^{j}2
j
的区间的最大值,例如 {f[1] [1]}f[1][1] 表示的是以1开始长度为2的区间的最大值, {f[1] [2]}f[1][2]表达的是以1开始长度为4的区间的最大值。我们可以看到 {j}j 每增加1,区间的长度乘以二,于是两个相邻区间合并就可以得到当前这个长度的区间的最大值了,也就是说 f[i] [j] = max(f[i] [j-1], f[i+2^{j-1}] [j-1])f[i][j]=max(f[i][j−1],f[i+2
j−1
][j−1]),这样 {O(nlogn)}O(nlogn)的时间复杂度我们就可以维护出f数组。
知道了f数组我们怎么来求任意区间[l,r]的最大值呢?也很简单,我们用两个长度刚好大于(r-l+1)/2的区间拼起来就好了(一个左边界是l,一个右边界是r)`
void rmp_st(int n) //预处理ST表,数组中有n个元素
{
for(int i = 1; i <= n; i++) f[i][0] = a[i];
int m = (int)(log((double)n) / log(2.0));
for(int j = 1; j <= m; j++)//先循环j再循环i,因为必须要把长度为1的区间都算出来了才能求长度为2的
for(int i = 1; i+(1<<j)-1 <= n; i++)
f[i][j] = min(f[i][j-1], f[i+(1<<(j-12))][j-1]);
}
int rmp_find(int l, int r) //求区间 l 到 r 之间的最值
{
int k = (int)(log(1.0 * (r-l+1)) / log(2.0));
return min(f[l][k], f[r-(1<<k)+1][k