RMQ算法

  • 格式:doc
  • 大小:25.00 KB
  • 文档页数:1

RMQ(Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在[i,j]里的最小(大)值。

最简单的算法我就不解释了,直接搜。

但是对于数据量非常大时,这种方法并不适用。

所以我们可以使用线段树来记录这个最大(小)值,效率咋算我还不是很了解,反正是一个nlogn 形式的。

但是线段树的建立和查询都是这个效率。

不过有一个更好的方法,那就是ST算法(Sparse Table):它是一种动态规划的方法。

以最小值为例。

a为所寻找的数组,用一个二维数组f(i,j)记录区间[i,i+2^j-1]区间中的最小值。

其中f[i,0] = a[i];
所以,对于任意的一组(i,j),f(i,j) = min{f(i,j-1),f(i+2^(j-1),j-1)}来使用动态规划计算出来。

这个算法的高明之处不是在于这个动态规划的建立,而是它的查询:它的查询效率是O(1)!如果不细想的话,怎么弄也是不会想到有O(1)的算法的。

假设我们要求区间[m,n]中a的最小值,找到一个数k使得2^k<n-m+1,这样,可以把这个区间分成两个部分:[m,m+2^k-1]和[n-2^k+1,n]!我们发现,这两个区间是已经初始化好的!前面的区间是f(m,k),后面的区间是f(n-2^k+1,k)!这样,只要看这两个区间的最小值,就可以知道整个区间的最小值!不得不佩服想出这个算法的人啊!
具体的代码可以看poj 3264。

不过还是要说几个注意的地方:
开辟这个二维数组f的时候注意其第二维不要开的过大,因为2的指数会很大的,到时候在自己机器上都无法运行。

在动态规划计算数组f的时候,用对2取对数来计算上面说的k,那样速度好一点。

计算出k 后,注意对循环控制变量的范围控制,而且一旦超出了范围,那么该值便不必计算。

算指数的时候可以用>>和<<来计算,不过注意加括号。

在查询的时候,k值仍然可以用对2取对数。