Balanced Lineup POJ - 3264(RMQ)
阿新 • • 發佈:2018-12-01
Balanced Lineup POJ - 3264
題目連線
題意:給出一個數列,Q個詢問,問區間[A, B]中最大值與最小值的差;
思路:線段樹可以做,維護最大最小值,直接查詢就可以;但是現在要用RMQ做;
何為RMQ?(Range Minimum/Maximum Query) 區間最值詢問,通過O(nlogn)的預處理可以在O(1)的時間內找到區間的最值;下面以最大值為例:
令Fmax[i][j]表示區間[i, i+2^j]中的最大值;那麼F[i][j]=max(F[i][j-1], F[i+2^(j-1)][j-1]);
init(){
for(int j=1; (1<<j)<=n; j++){
for(int i=1; i+(1<<j)-1<=n; i++){
Fmax[i][j]=max(Fmax[i][j-1], Fmax[i+(1<<(j-1))][j-1]);
}
}
}
對於區間[A, B]內的詢問有:
int k=(int)(log(B-A+1.0)/log(2.0));
query(A, B)=max(Fmax[A][k], Fmax[B-(1<<k)+1][k]);
本題程式碼:
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <math.h>
using namespace std;
const int maxn=5e4+10;
int Fmax[maxn][20], Fmin[maxn][20], n, Q;
void init(){
for(int i=1; (1<<i)<=n; i++){
for(int j=1; j+(1<<i)-1<=n; j++){
Fmax[j][i]=max(Fmax[j][i-1 ], Fmax[j+(1<<(i-1))][i-1]);
Fmin[j][i]=min(Fmin[j][i-1], Fmin[j+(1<<(i-1))][i-1]);
}
}
}
int main(){
while(~scanf("%d%d", &n, &Q)){
for(int i=1; i<=n; i++){
scanf("%d", &Fmax[i][0]);
Fmin[i][0]=Fmax[i][0];
}
init();
while(Q--){
int x, y;
scanf("%d%d", &x, &y);
int k=(int)(log(y-x+1.0)/log(2.0));
printf("%d\n", max(Fmax[x][k], Fmax[y-(1<<k)+1][k])-min(Fmin[x][k], Fmin[y-(1<<k)+1][k]));
}
}
return 0;
}