rmq查询区间最值

rmq:
时间复杂度:O(nlogn)的时间复杂度,利用动态规划进行预处理,dp[i][j], i:代表以i为起点,j:代表 i+(1<<j)-1 的长度,dp[i][j]代表:[i,i+(1<<j)-1]区间的最大值,由于区间的合并性质,可以写出所有以 i 为起点 i+(1<<j)-1长度的区间最大值

查询操作:
查询区间[l,r],由于log2(r-l+1)可能是小数,并不能包含整个[l,r]区间,所以我们需要查询上下两部分max(dp[l][k],dp[r-(1<<k)+1][k]),覆盖了[l,r]区间,值得一提的是,查询操作是O(1)的复杂度

预处理操作:

void init_rmq()
{
    for(int i=1;i<=n;i++)
    {
        dp[i][0]=a[i];
    }
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=1;i+(1<<j)-1<=n;i++)//有效区间
        {
            dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
        }
    }
}

查询操作:

int rmq(int l,int r)
{
    int k=log2(r-l+1);
    return max(dp[l][k],dp[r-(1<<k)+1][k]);

}

完整代码:
ST表传送门

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int dp[maxn][32],n,a[maxn];
void init_rmq()
{
    for(int i=1;i<=n;i++)
    {
        dp[i][0]=a[i];
    }
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=1;i+(1<<j)-1<=n;i++)//有效区间,代表i后面又i+(1<<j)-1位
        {
            dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
        }
    }
}
int rmq(int l,int r)
{
    int k=log2(r-l+1);
    return max(dp[l][k],dp[r-(1<<k)+1][k]);

}
int main()
{
    int q;
    cin>>n>>q;
    for(int i=1;i<=n;i++)
       scanf("%d",&a[i]);
        init_rmq();
    while(q--)
    {
        int l,r;
      scanf("%d %d",&l,&r);
      printf("%d\n",rmq(l,r));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值