ST表详解+模板

ST表

基本概念

ST表是一个用来处理区间最值查询(RangeMaximum/Minimum Query)的离线算法。该算法分 为离线预处理O(n log n)和查询O(1)两个部分,其用到了倍增的思想。

某个区间查询问题是否适用ST表,关键在于其进行的操作是否允许区间重叠,例如max(a,b,c) = max{max(a,b),max(b,c)}就可以用ST表维护,而区间和问题则不能维护。

问题描述

给定一个长度为n的序列,有m次询问,每次给定区间[L , R],求区间内最大值。

算法思路

定义st表

我们设 st[i][j] 为从 i 开始的向后 2^j 个数中的最大值。假设这n个数存放的序列a中,根据定义 st[i][j] = max{a[k] | i <= k <= i+2^j - 1}。

查询操作

假设,我们要查询区间 [L,R] 中的最大值,由ST表定义,我们可知,我们可以查询从 x 开始,直至区间末尾的任意区间,由此特性,我们豁然开朗:以 区间[L,R] 为例,我们可以查询区间 [L,x] (x 是不超过 R 的最大数);同理,我们也可以查询区间 [x,R] (x 是不小于 L 的最小数);
由此得解
ans = max {st[L][k],st[R - (1<
这里的k要取,使 L+2^k <= R 的最大值;

预处理

我们在上述证明了查询操作确实是O(1)的,所以如果我们真的能按照st表定义的那样去更新它,那 么该算法就真正的完成了。更新st表用到了动态规划的思想。
更新中仍然用到了倍增的思想,使得更新操作从O(n^2)优化到了O(n log n),初始状态st[x][0] = a[x],st[x][j] = max(st[x][j-1] , st[x + 1<<(j-1) ][j-1])。其思想和上述重叠查询类似,不再赘述。 但是要注意更新顺序,因为其中 j (第二维)才是阶段,而第一维 x 是状态,所以对于 j 的循环要 放在最外层。

模板

预处理
void init(){
    Log[1] = 0;//预处理log函数
    for(int i = 2;i <= n+1;i++) 
        Log[i] = Log[i/2]+1;
    for(int i = 1;i <= n;i++)
         st[i][0] = a[i];
    for(int j = 1; (1<

你可能感兴趣的:(ST表,RMQ问题)