概念
我们用 st[i][j] 来表示原数组 a[n] 中区间 [ i , i + 2 j − 1 ] [i, i + 2^j - 1] [i,i+2j−1] 内的最大值, 以实现用 O(1) 的复杂度来查询任意区间 [p, q] 的最大值, 具体怎么实现看下文。
初始化
我们对 st[i][0] 进行初始化
for (int i = 1; i <= n; i++)
st[i][0] = a[i];
进一步初始化(构造st表)
int p = log(n)/log(2);
for (int j = 1; j<= p; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
查询
int query(int p, int q) {
int k = log(q - p + 1)/log(2);
return max(st[p][k], st[q - (1 << k) + 1][q]);
}
完整代码
// 建表复杂度 nlogn, 查询复杂度 1
#include <iostream>
#include <cmath>
#define MAXN 100
using namespace std;
struct ST{
int f[MAXN][MAXN];
void build(int a[], int n){
for (int i = 1; i <= n; i++)
f[i][0] = a[i];
int k = log(n) / log(2);
for (int j = 1; j <= k; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
int query(int l, int r){
int q = log(r - l + 1) / log(2);
return max(f[l][q], f[r - (1 << q) + 1][q]);
}
};
int main(){
int a[11] = {0, 5, 3, 7, 2, 12, 1, 6, 4, 8, 15};
ST st1;
st1.build(a, 10);
cout << st1.f[3][3] << endl;
cout << st1.query(2, 8) << endl;
return 0;
}