1. 程式人生 > >RMQ - ST算法

RMQ - ST算法

ems 一個 sca scanf nbsp target iostream light ret

題目鏈接

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

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;
}

RMQ - ST算法