st表
用来解决区间最大值最小值问题, O(nlogn)预处理,O(1)查询
思想:倍增
二维数组f的含义
f[i][j],指的是在序列的第i项,向后2^j个元素所包含序列间的最大(小)值。
所以f[i][j]表示从i到i + 2^j - 1的区间
已 i = 1为例
图中f[1][2]f[1][2]即可由max(f[1][1],f[3][1])max(f[1][1],f[3][1])转移来
int f[MAXN][21]; // 第二维的大小根据数据范围决定,不小于log(MAXN)
for (int i = 1; i <= n; ++i)
f[i][0] = read(); // 读入数据
for (int i = 1; i <= 20; ++i)
for (int j = 1; j + (1 << i) - 1 <= n; ++j)
//需要进行-1,由于总长度是从j开始,长度为(1 << i),结尾的位置为j + (1 << i) - 1
f[j][i] = max(f[j][i - 1], f[j + (1 << (i - 1))][i - 1]);
注意1<<i 相当于 2的i次方
计算log
int s = log2(r - l + 1);
l + 2^s - 1尽可能靠近r 得s = log(r - l + 1)
在线查询
for (int i = 0; i < m; ++i)
{
int l = read(), r = read();
int s = log2[r - l + 1];//直接使用cmath中的log2函数
printf("%d\n", max(f[l][s], f[r - (1 << s) + 1][s]));
}//在线查询
注意
查询时f的区间划分问题,f[l][s]表示从l开始经过2^s个数字,终点为l + 2^s - 1, f[r-2^s+1][s]表示终点为r