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

数据结构专题小结:RMQ问题

时间:2015-03-19 22:14:17      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:rmq问题

RMQ问题

范围最小值问题(Range Minimum Query)是指:给定一个n个元素的数组A[1],A[2]...A[n]。设计一个数据结构,支持查询操作Query(L,R):计算min{A[L],A[L+1]...A[R]}。

该问题在实践中常用Tarjan的Sparse-Table算法。它的预处理时间是O(N*logN),但查询只需要O(1),而且常数非常小。最重要的是,这个算法非常好写,而且不易写错。

(1)原理:该算法利用了分治法的思想,令d(i,j)表示从i开始的,长度为2^j的一段元素中的最小值。则不难发现如下公式成立:

d(i,j)=min{d(i,j-1),d(i+2^(j-1),j-1)}

注意到2^i≤n,因此d数组的元素个数不超过n*logn个,而每一项都能在常数时间内算完。因此总的时间复杂度是O(N*logN)。

#define N 1000
int d[N][N];
vector<int>A;
#define INF 100000000
void RMQ_init(const vector<int>&A)//初始化操作,所有元素放到vector中
{
	for (int i = 0; i < N;i++)
	for (int j = 0; j < N; j++)
		d[i][j] = INF;
	int n = A.size();
	for (int i = 0; i < n; i++)
		d[i][0] = A[i];
	for (int j = 1; (1 << j) <= n;j++)
	for (int i = 0; i + (1 << j) - 1 < n; i++)
		d[i][j] = min(d[i][j - 1], d[i + (1 << (j - 1))][i - 1]); 
}

查询操作也很简单,令k为满足2^k≤R-L+1的最大整数,则以L开头,以R结尾的两个长度为2^k的区间合起来即覆盖了查询区间[L,R]。由于是最小值,有些元素重复考虑了也没有关系。

 

int RMQ(int L, int R)
{
	int k = 0;
	while ((1 << (k + 1)) <= R - L + 1)k++;
	return min(d[L][R], d[R - (1 << k) + 1][k]);
}


数据结构专题小结:RMQ问题

标签:rmq问题

原文地址:http://blog.csdn.net/u014800748/article/details/44460777

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