Sparse Table 的缩写 ------> ST表
ST表就是我们的dp数组
下面有一个整数序列
索引i | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
a[i] | 4 | 6 | 5 | 8 | 9 | 1 |
如果有m次询问,询问索引值在 [L,R]区间 的元素中的最大值
第i次询问 | L | R | MAX |
1 | 4 | 6 | 9 |
2 | 2 | 3 | 6 |
3 | 1 | 6 | 9 |
我们很容易得到上述的表格,思考一下大脑是如何得到MAX值的,没错,是遍历区间
很容易我们可以按照遍历区间的算法实现,时间复杂度为O(n3)
考虑优化,用空间换时间。
dp[i][j] 表示 以i为起点,以j为终点的区间中的最大值
很容易得到状态转移方程 dp[i][j] = max(dp[i][j-1], a[j])
O(n)复杂度
得到dp[1][1]~dp[1][n]
dp[1][1] = a[1]
dp[1][2] = max(dp[1][1],a[2])
.......
dp[1][n] = max(dp[1][n-1],a[n])
依次类推得到
dp[2][2]~dp[2][n]
dp[3][3]~dp[3][n]
........
dp[n-1][n-1]~dp[n-1][n]
dp[n][n]
时间复杂度:O(n2)
重点来了!!!
考虑优化上述dp过程,我们发现以1为起点要算n次,以2为起点要算n-1次,重叠部分过多,我们思考是否有一种方法可以使得重叠部分变少。
这种办法就是倍增
dp[i][j] 表示 以 i 为起点,区间长度为 2的j次方 的区间中的最大值
比如说
dp[1][0] : 以 1 为 起点, 区间长度为 1(2的0次方)的区间 即[1,1]的最大值
dp[4][2]: 以 4 为 起点, 区间长度为 4(2的2次方)的区间 即[4,7]的最大值
求[ 3, 9 ] 区间的最大值
区间长度 9-3+1 = 7 = 2的2次方 + 2的1次方 + 2的0次方
所以最大值 = max( dp[3][2],dp[3+2的2次方][1], dp[3+2的2次方+2的1次方][0])
即 max(dp[3][2], dp[7][1], dp[9][0])
这次查询的时间复杂度为log2n
dp数组如何求?
枚举起点,区间长度为1的情况
dp[1][0] = a[1]
dp[2][0] = a[2]
........
dp[n][0] = a[n]
由区间长度1推出区间长度2
依次类推得到dp数组所有元素的值
x = int(log2(n));
for (int i=1; i<=n; i++) dp[i][0] = a[i];
for (int i=1; i<=x; i++) {
for (int j=1; j<=n; j++) {
// 分成两段
dp[j][i] = max(dp[j][i-1], dp[j+(1<<(i-1)][i-1]);
}
}