rmq_ST算法

ST算法: 为离线算法,查询最值问题


    minn[i][j]表示区间 [i , i+(1<<j)-1] 的最小值,minn[i][j]一定是偶数个数的最小值,所以对它一分为二
    状态方程:minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1])
    查询[l,r]区间时,区间个数是r-l+1, k为log2(r-l+1),那么最小值为minn[l][k],
    因为log2(r-l+1)可能存在一点误差,即判断一下后端点
    即min(minn[l][k],minn[r-(1<<k)+1][r])
    最大值:
        同理

 

代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e5+7;
int minn[N][21],maxx[N][21],n;
int Log2[N];//表示log2(i)
void ST()
{
    for(int i = 0; i <= n; i ++)Log2[i] = (i == 0 ? -1 : Log2[i >> 1] + 1);
    for(int j=1;j<21;j++)
        for(int i=1;i+(1<<j)<=n+1;i++)
        {
            minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
            maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]);
        }
}
int query_min(int l,int r)
{
    int k=Log2[r-l+1];
    return min(minn[l][k],minn[r-(1<<k)+1][k]);
}
int query_max(int l,int r)
{
    int k=Log2[r-l+1];
    return max(maxx[l][k],maxx[r-(1<<k)+1][k]);
}
int main()
{
    int q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&minn[i][0]);
        maxx[i][0]=minn[i][0];
    }
    ST();
    while(q--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",query_max(l,r)-query_min(l,r));
    }
    return 0;
}

 

posted @ 2018-01-29 20:03  jadelemon  阅读(233)  评论(0编辑  收藏  举报