RMQ - ST算法

题目链接

---------------------------------------------------------------------------------

pre[len][L]表示左边界为L,长度为Len的区间中的最小值;

那么对于一个询问[L,R],我只要找到小于这个区间长度的最大的2的非负整数次幂(T),那么这个区间中的最小值就是min{pre[T][L],pre[T][R-T+1]}

一直tle,把cin改成scanf后ac了,==。

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#define MAX(a,b) ((a)>=(b)?(a):(b))
#define MIN(a,b) ((a)<=(b)?(a):(b))
#define OO 0x0fffffff
using namespace std;
typedef long long LL;
const int N = 1000100;
int pre[32][N];
int pow2[32];
int get(int data){
    if(!data) return 0;
    int ret = 0;
    while(data){
        data>>=1;
        ret++;
    }
    return ret-1;
}
int main(){
    for(int i=0;i<32;i++) pow2[i]=(1<<i);

    int n; cin>>n;
    for(int i=0;i<n;i++) scanf("%d",&pre[0][i]);

    int maxLen = get(n);
    for(int len=1;len<=maxLen;len++)
    for(int i=0;i+pow2[len]<=n;i++){
        pre[len][i] = MIN(pre[len-1][i],pre[len-1][i+pow2[len-1]]);
    }

    int q,a,b,c; cin>>q;
    while(q--){
        scanf("%d%d",&a,&b);
        a--,b--;
        c = get(b-a+1);
        printf("%d\n",MIN(pre[c][a],pre[c][b-pow2[c]+1]));
    }
    return 0;
}

 

posted @ 2017-05-31 20:07  redips  阅读(157)  评论(0编辑  收藏  举报