RMQ
RMQ(Range Maximum/Minimum Query),即区间最值查询问题。
初始化
时间复杂度:O(n*log2 n)
st[ i ][ j ],存储的是 i 到 i + 2^j - 1的最值。
首先初始化st[ i ][ 0 ] = a[ i ]
len = r - l + 1,k = log2(len),2^k >= t/2
[l, r]的最值 也就是求[l, l + 2k] 和 [ r - 2k, r]的最值,两者有交集,所以得出的结果就是[ l, r ]的最值
遍历上一步进行初始化
查询
时间复杂度:O(1)
例如查询区间为[ l, r]
就是查询k = log2(r - l + 1), st[ l ][ k] 和 st[ r - 2k, k]的最值
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int n, m;
int st[maxn][30], a[maxn], Log[maxn];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void init(){
for(int i = 1; i <= n; i++)
st[i][0] = a[i];
for(int i = 1; (1 << i) <= n; i++){
for(int j = 1; j + (1 << i - 1) <= n; j++){
st[j][i] = max(st[j][i - 1], st[j + (1 << i -1)][i - 1]);
}
}
for(int i = 1; i <= n; i++)
Log[i] = log2(i);
}
int search(int l, int r){
int k = Log[r - l + 1];
return max(st[l][k],st[r - (1 << k) + 1][k]);
}
int main(){
n = read(), m = read();
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
init();
int l, r;
while(m--){
scanf("%d%d", &l, &r);
printf("%d\n", search(l, r));
}
return 0;
}