RMQ 求区间最值

来源:互联网 发布:linux开机启动shell 编辑:程序博客网 时间:2024/06/05 03:36

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<

原创粉丝点击