RMQ 求區間最值

pku 3264

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int N=5e4+7;
int a[N];
int n;
int mx[N][20],mi[N][20];
void rmq()//預處理O(nlogn)
{
    for(int i=1; i<=n; i++)
        mx[i][0]=a[i],mi[i][0]=a[i];//初始狀態
    for(int j=1; (1<<j)<=n; j++)//兩層for不能反,自己思考一下
        for(int i=1; i+(1<<j)-1<=n; i++)
        {
            mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
            mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
        }
}
int query(int l,int r)//查詢 O(1)
{
    int k=trunc(log2(r-l+1));//即取整,去尾
    //  trunc(number,num_digits)
    //  Number 需要截尾取整的數字。
    //  Num_digits 用於指定取整精度的數字。Num_digits 的默認值爲 0。
    return (max(mx[l][k],mx[r-(1<<k)+1][k])-min(mi[l][k],mi[r-(1<<k)+1][k]));//預處理已經完全 可直接返回
}
int main()
{
    int q;
    while(~scanf("%d%d",&n,&q))
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        rmq();
        for(int i=0;i<q;i++)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d\n",query(l,r));
        }
    }
}

RMQ算法不能修改
dp[i][j] 代表從 i 到 i+2^j-1 的最大/小值

預處理:dp[i][0]爲最初始

查詢 l 到 r 的最值:k是小於(r-l+1)最小的2的冪次那麼l到l+(1<

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章