RMQ区间最值查询(ST表)
可学习的博客:
博客园 - gaoyanliang 的博客
博客园 - Wolfloral的博客
代码
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <set>
#include <math.h>
using namespace std;
const int N = 5e4+10;
int mnn[N][30], mxx[N][30], x[N];
int main(){
int n,q;
cin>>n>>q;
for(int i = 1; i <= n; i++) cin>>x[i],mnn[i][0] = mxx[i][0] = x[i];
for(int j = 1; (1<<j) <= n; j++){
for(int i = 1; i + (1<<j)-1 <= n; i++)
mnn[i][j] = min(mnn[i][j-1], mnn[i+(1<<(j-1))][j-1]),
mxx[i][j] = max(mxx[i][j-1], mxx[i+(1<<(j-1))][j-1]);
}
while(q--){
int l,r, len = 0;
cin>>l>>r;
while((1<<(len+1) <= r - l + 1)) len++;
// 输出 区间最大值与最小值的差
cout<< max(mxx[l][len],mxx[r - (1<<len)+1][len]) -
min(mnn[l][len],mnn[r-(1<<len)+1][len]) <<endl;
}
return 0;
}
ST表
ST 表预处理时间复杂度为 O(nlogn) 查询为O(1)
将一段区间的最值通过两个子区间取得
例如将 左端点i = 3,长度为 2j 的区间[2, j] 分为 2个长度为 2j-1 的区间 [2, j-1] 和 [i + (1<<(j-1) ), j-1]
因此 区间[2,j] 的最值可以通过 上述两个子区间取得
查询时,同样是通过两个区间,这两个区间可能会有重叠部分,例如:l = 3, r = 8的长度为 6 的区间 可以通过两个长度为4的区间 l = 3, r = 6 (也就是[3,2] ) 和 l = 5,r = 8 (区间 [5,2] )