RMQ问题 Page 41 ST算法
http://www.51nod.com/Challenge/Problem.html#!#problemId=1174
第一次写博客 这是51nod上一个简单的基础题。
大致题意:给一组数组 让你判断T个 [ l , r ] [l,r] [l,r]区间里的最大值(或最小值)。
分析:暴力肯定会TLE。
根据倍增思想,需要引入2的整数次幂用来简化时间和空间,那么具体该怎么做呢?
先取数组 d p [ i ] [ j ] dp[i][j] dp[i][j],表示从 i i i开始的 2 j 2^j 2j个数中的最大值,即区间 [ i , i + 2 j − 1 ] [i,i+2^j-1] [i,i+2j−1]。
接下来很容易理解的转移方程,从 i i i开始的 2 j 2^j 2j个数中的最大值肯定是其左半段和右半段的最大值,这个左半段和右半段完美契合2的整数次幂思想,只需要把幂次-1即可!
dp[i][j]=max(dp[i][j-1],dp[i+1<<(j-1)][j-1]);
预处理代码如下:
void ST()
{
for (int i=1;i<=n;i++)dp[i][0]=a[i];//区间长度为1的区间最大值为本身
int t=log(n)/log(2)+1;
for (int j=1;j<t;j++)
{
for (int i=1;i<=n-(1<<j)+1;i++)
{
dp[i][j]=max(dp[i][j-1],dp[i+1<<(j-1)][j-1]);
}
}
}
接下来就是查询问题了,如果区间长度正好是 2 k 2^k 2k,那么我们可以直接取 d p [ r − 2 k + 1 ] [ k ] dp[r-2^k+1][k] dp[r−2k+1][k]作为答案,那么如果区间不正好是2的整数次幂应该如何处理?
只需要直接覆盖即可,不过这个覆盖不是随便覆盖,范围肯定是不能超出给出的 [ l , r ] [l,r] [l,r]的
取一个 k k k,满足 2 k ≤ r − l + 1 < 2 k + 1 2^k \leq r-l+1<2^{k+1} 2k≤r−l+1<2k+1,那么以 l l l为开头开始的 2 k 2^k 2k个数和以 r r r结尾的 2 k 2^k 2k个数肯定覆盖了整个区间~
查询代码如下:
int ST_query()
{
int k=log(r-l+1)/log(2);
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
综上所述:
ST算法的时间复杂度为:
预处理: O ( n l o g n ) O(nlogn) O(nlogn)
查询: O ( 1 ) O(1) O(1)
RMQ问题同样可以用线段树解决,倍增思想实在是好。
刚开始学 继续钻研