ST表的用处是处理区间最值问题
对于一个数组a[n]
设另一个数组f[n][m]
对于f数组中的一项f[i][j]
表示从a[n]
中的第i项开始,在长度为2^m(2的m次方)的区域内的最大值
f[i][0]
指a[i]
自己
利用递推的方式得到ST表
递推方式:
对于一个区间最大值[L,R]设置为F[i][j]
其最大值等同于max([L,mid],[mid+1,R]
那么其中[L,mid]等同于F[i][j-1]
而对于[mid+1,R]等同于F[i+(1<<(j-1))][j-1]
所以f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
对于问询区间[L,R],设K是2为底的log(L) ,那么同样可以由F[L][K]
与F[R-(1<<k)+1][K]
来组合出问询区间[L,R]max(f[l][k], f[r - (1 << k) + 1][k]);
完整代码
```cpp
#include <iostream>
using namespace std;
const int N = 2e5 + 10, M = 18;
int n, m;
int w[N];
int f[N][M];
int log[N];
void init() {
for (int i = 2; i <= N; i++) {
log[i] = log[i >> 1] + 1;
}
for (int j = 0; j < M; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
if (!j)
f[i][j] = w[i]; //只有一个数
else
f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
}
}
}
int query(int l, int r) {
int len = r - l + 1;
int k = log[len] ;
return max(f[l][k], f[r - (1 << k) + 1][k]);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> w[i];
init();
cin >> m;
while (m--) {
int a, b;
cin >> a >> b;
cout << query(a, b) << endl;
}
}