码迷,mamicode.com
首页 > 其他好文 > 详细

RMQ问题与ST算法

时间:2014-08-08 17:34:26      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   for   art   ar   

RMQ(Range Minimum/Maximum Query)问题是求区间最值问题。

对于长度为 n 的数组 A,进行若干次查询,对于区间 [L,R] 返回数组A中下标在 [L,R] 中的最小(大)值。

可以用线段树来解决这个问题,预处理的复杂度是 O(nlogn),查询的复杂度是 O(logn)。

更好的解法是ST算法。Sparse_Table算法,即稀疏表算法,这个方法可以在 O(nlogn) 的预处理后达到 O(1) 的查询代价。

这个算法非常容易实现。

 

定义 F[ i, k ] 表示从 i 开始的,长度为 2^k 的区间内元素的最小值。

当 k = 0 时,F[ i, 0 ] 的值显然就是A[ i ] 的值。

而 k > 0 时,对于从 i 开始的长度为 2^k 的区间,它的最小值显然是从 i 开始的长度为 2^(k-1) 的区间中的最小值与从 i+2^(k-1)开始的长度为 2^(k-1) 的区间中的最小值中更小的那一个。

则有递推公式 F[ i, k ] = min{ F[ i, k-1 ], F[ i+2^(k-1), k-1] }

由于 2^k<=n,因此 F 数组中的元素个数不会超过 nlogn,而每个元素都可以在O(1)的时间内计算出,因此总时间为O(nlogn)。

bubuko.com,布布扣
1 int F[maxn][20];
2 //元素从1编号到n
3 void RMQ_init(int A[],int n){
4     for (int i=1;i<=n;i++) F[i][0]=A[i];
5     for (int k=1;(1<<k)<=n;k++)
6         for (int i=1;i+(1<<k)-1<=n;i++)
7             F[i][k]=min(F[i][k-1],F[i+(1<<(k-1))][k-1]);
8 }
RMQ的预处理

 

对于查询操作 [L,R],定义 k 为满足 2^k<=R-L+1 的最大整数。

则以L开头的长度为 2^k 的区间与以R结尾的长度为 2^k 的区间,能够完整的覆盖区间 [L,R]。

因此这两个区间的最小值中更小的那一个就是所查询的区间 [L,R] 的最小值。

bubuko.com,布布扣
1 int RMQ(int L,int R){
2     int k=0;
3     while ((1<<(k+1))<=R-L+1) k++;
4     return min(d[L][k],d[R-(1<<k)+1][k]);
5 }
RMQ查询

ST 算法也可以求出最值所在的下标,只要将 F 数组中储存的值变为数组 A 的下标即可。

 

RMQ问题与ST算法,布布扣,bubuko.com

RMQ问题与ST算法

标签:style   blog   http   color   os   for   art   ar   

原文地址:http://www.cnblogs.com/zinthos/p/3899582.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!