RMQ求范围最值(模板)

      现在有n个元素的数组a(0),a(1),a(2)…a(n-1),设计一个数据结构,对于每次询问Query(L,R),都可以快速查询a(L),a(L+1)…a(R)的最小值,即min{a(L),a(L+1)…a(R)}
      利用动态规划思想,可以做到O(nlogn)预处理,O(1)查询. 预处理时,设dp(i,j)表示从i开始,长度为2^j的一段元素中的最小值,那么状态转移方程是 dp(i,j)=min{dp(i,j-1),dp(i+2^(j-1),j-1)}. 查询时,令k为满足2^k<=R-L+1的最大整数,则查询结果即为min{dp(L,k),dp(R-2^k+1,k)}

#include<bits/stdc++.h>
using namespace std;
typedef int type;

const int maxn=1e5+5;

struct RMQ{
    int n;            //n个元素
    type a[maxn];       //序列
    type dp[maxn][30];

    void init(){//预处理 O(nlogn)
        for(int i=0;i<n;++i) dp[i][0]=a[i];
        for(int j=1;(1<<j)<=n;++j){
            for(int i=0;i+(1<<j)-1<n;++i){
                dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);//最小值
                //dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);//最大值
            }
        }
    }

    type query(int le,int ri){//查询[le,ri]的最值 O(1)
        int k=0;
        while((1<<(k+1)) <= ri-le+1) ++k;
        type ans=min(dp[le][k],dp[ri-(1<<k)+1][k]);//最小值
        //type ans=max(dp[le][k],dp[ri-(1<<k)+1][k]);//最大值
        return ans;
    }
};

int n,q;
RMQ rmq;

int main(){
    scanf("%d%d",&n,&q);
    rmq.n=n;
    rmq.q=q;
    for(int i=0;i<n;++i) {
        scanf("%d",&rmq.a[i]);
        //scanf("%lld",&rmq.a[i]);
    }
    rmq.init();
    while(q--){
        int le,ri;
        scanf("%d%d",&le,&ri);//[0,n-1]
        type ans=rmq.query(le,ri);
        printf("%d\n",ans);//printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao_k666/article/details/80425479
今日推荐