数列区间最大值 RMQ问题(ST算法模板)

问题:

输入一串数字,给你 M个询问,每次询问就给你两个数字 X,Y,要求你说出 X 到 Y 这段区间内的最大数。

输入格式

第一行两个整数 N,M 表示数字的个数和要询问的次数;
接下来一行为 N 个数;
接下来 M 行,每行都有两个整数X,Y 。

输出格式

输出共 M 行,每行输出一个数。

样例

样例输入

10 2
3 2 4 5 6 8 1 2 9 7
1 4
3 8

样例输出

5
8

ST算法:ST算法是解决RMQ(区间最值)问题,它能在O(nlogn)的时间预处理,然后O(1)回答。其原理是倍增,h[i][j]表示从i位起的2^j个数中的最大数,即[i,i+2^j-1]中的最大值。

流程:h[i][0]表示从 i 开始到2^0个数之间中的最大值,只能是 a[i],故 h[i][0]=a[i]。
对于任意的 h[i][j],我们分成两段相等长度的数列来看,[ i , i+2^(j-1)-1] 和 [ i+2^(j-1) , i+2^j-1 ],分别对应 h[i][j-1] 和 h[i+(1<

例如 x 到 y 之间的最大值。

k=log2(y-x+1);//区间的长度

max(h[x][k],h[y-(1<

可以代数尝试一下,推一下就明白了我代的数是x=2,y=20,k=4,也就是(2~17)和(5~20)这两个区间。

模板代码:

#include
#include
#include
#define N 100005
#include
using namespace std;
const int M=25;
int h[N][M],a[N];//h[i][j]表示从i位起的2^j个数中的最大数
int main()
{
    int n,m,x,y;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        h[i][0]=a[i];//h[i][0]表示[i,i]中的最大值,只能是a[i],故h[i][0]=a[i]。
    }
    for(int j=1; j<=log2(n); j++)
        for(int i=1; i+(1<

 

你可能感兴趣的:(RMQ,(ST算法))