浅谈RMQ
所谓\(RMQ\),就是\(Range\) \(Minimum/Maximum\) \(Query\),区间最值查询。我们可以用线段树维护,也可以使用笛卡尔树将其转化为求\(lca\)的问题。但是后者一般不常用,更为常用的,是家喻户晓的\(st\)算法。由于\(RMQ\)问题大多不是赤裸裸的\(RMQ\),而是经过了伪装。所以\(st\)算法显得尤为重要。
嗯,我也不清楚这有什么关系。但是先不说能不能看破\(RMQ\)的伪装,\(st\)算法总得会嘛,\(st\)都不会看破伪装不照样\(GG\)……
\(st\)算法
\(st\)算法用了\(dp\)的思想,我们设\(f[i][j]\)表示从当前序列第\(i\)位开始,一直到\(i+2^j-1\)结束最大值在哪一位。
那么\(f[i][j]\)就可以由\(f[i][j-1]\)与\(f[i+2^j][j-1]\)更新得来。预处理\(f\)数组需要\(O(nlogn)\)的时间。
求出\(f\)数组之后,我们就可以\(O(1)\)的查询区间\([l,r]\)的最大值了。设\(len=r-l+1\),假设存在一个\(x\)满足:
\(2^x\leqslant len\)且\(len\leqslant 2^{x+1}\)。那么\(f[l][x]\)与\(f[r-2^x+1][x]\)的最大值就是区间\([l,r]\)的最大值。因为\([l,l+2^x-1]\)与\([r-2^x+1,r]\)肯定会将区间\([l,r]\)覆盖,即使重合了也没关系,最大值还是最大值。我还是菜鸡
\(st\)算法会了之后就可以愉快的去写\(RMQ\)了。如果你看不破题目的伪装,那就去与\(RMQ\)的战场上走一遭吧,能活着回来你就会了。