RMQ - 区间最大值问题

RMQ - 区间最大值问题

倍 增 + 动 规 预 处 理 数 组 f [ i ] [ j ] 。   f [ i ] [ j ] : 以 i 为 起 点 , 长 度 为 2 j 的 区 间 里 的 最 大 值 。   状 态 转 移 方 程 f [ i ] [ j ] = m a x ( f [ i ] [ j − 1 ] , f [ i + 2 j − 1 ] [ j − 1 ] ) , 即 将 区 间 一 分 为 二 , 取 两 个 子 区 间 的 较 大 值 。   查 询 长 度 为 l e n 的 区 间 [ l , r ] 的 最 大 值 : 与 预 处 理 过 程 类 似 , 找 到 一 个 最 大 的 整 数 k , 使 得 2 k < = l e n , 那 么 两 个 长 度 为 2 k 的 区 间 必 能 覆 盖 长 度 为 l e n 的 区 间 。 答 案 仍 然 是 取 m a x ( f [ l ] [ k ] , f [ r − 2 k + 1 ] [ k ] ) 。 倍增+动规预处理数组f[i][j]。\\\ \\f[i][j]:以i为起点,长度为2^j的区间里的最大值。\\ \ \\状态转移方程f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1]),即将区间一分为二,取两个子区间的较大值。\\ \ \\查询长度为len的区间[l,r]的最大值:\\与预处理过程类似,找到一个最大的整数k,使得2^k<=len,\\那么两个长度为2^k的区间必能覆盖长度为len的区间。\\答案仍然是取max(f[l][k],f[r-2^k+1][k])。 +f[i][j] f[i][j]i2j f[i][j]=max(f[i][j1],f[i+2j1][j1]) len[l,r]k使2k<=len2klenmax(f[l][k],f[r2k+1][k])

起 点 i 有 n 个 , 长 度 j 有 l o g 2 n 个 , 预 处 理 时 间 复 杂 度 O ( n l o g 2 n ) 。 起点i有n个,长度j有log_2n个,预处理时间复杂度O(nlog_2n)。 injlog2nO(nlog2n)

例题:

输 入 长 度 为 n 的 序 列 a 1 , a 2 , . . . , a n 。 以 及 q 个 询 问 , 每 个 询 问 包 括 区 间 的 左 右 端 点 l , r , 对 每 个 询 问 输 出 区 间 最 大 值 。 输入长度为n的序列a_1,a_2,...,a_n。以及q个询问,每个询问包括区间的左右端点l,r,对每个询问输出区间最大值。 na1,a2...anql,r,

数据范围:
1≤n≤2×100000,
1≤q≤10000

输入样例:
6
34 1 8 123 3 2
4
1 2
1 5
3 4
2 3
输出样例:
34
123
123
8

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>

using namespace std;

const int N=2e5+10;
int n,a[N],q,f[N][18];

void init()
{
    for(int j=0;j<18;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
            if(!j) f[i][j]=a[i];
            else f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);
}

int query(int l,int r)
{
    int len=r-l+1;
    int k=log(len)/log(2);
    
    return max(f[l][k],f[r-(1<<k)+1][k]);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值