用途:对于一段区间的最大值 最小值 lcm等 用O(nlogn)预处理 O(1)查询
以本题为例:定义数组 rmq[i][j] 表示 \(i\) ~ \(i+2^k-1\) 区间内的最大值
预处理阶段类似LCA的倍增(This is LCA)
大循环是次数 以j-1为界限将一段区间分为两段:
然后是查询阶段 对于询问的一段区间 \([l,r]\) 这里我们选取一个最大的k 使得 $rmq[l][k] <= r $
实际上 \(k=\left\lfloor\log2(r-l+1)\right\rfloor\) 也好证:
且我们知道 两段子区间有重叠部分并不影响该区间最大值
所以我们取 \(2^k-1\) 长度的前缀和后缀作为两段子区间
用数组表示就是 rmq[l][k] 与 rmq[r+1-\(2^k\)][k]
且这两段区间一定是可以覆盖整个大区间的
我们可以使用反证法:假如这两段区间无法覆盖大区间 则 \(2^k-1\) 应小于区间长度 \(r-l+1\) 则此时取到的k就不是满足 $rmq[l][k] <= r $ 的最大值 与假设矛盾
查询代码如下:
附本题代码: