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

实用数据结构---RMQ问题

时间:2015-03-01 18:35:50      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:数据结构   rmq   算法   sparse-table   区间最值查询   

RMQ问题就是区间最小值问题,这是一个非常经典的题,

由他引申出来的也是不计其数最多的是给出一个区间,然后输入多组区间端点,求输入区间的最小值。

每次用循环来计算一个最小值显然不够快,怎么办呢?

实践中最常用的是Tarjan的 Sparse-Table算法,它的预处理时间是O(nlogn),但是查询只需要O(1),而且常数很小。

它的思想很简单,就是递推+二分的思想。我们先定义一个二维数组d[i][j]

代表从 i 开始,长度为2的j次幂的区间中的最小值

然后写出递推公式 d[i][j] = min( d[i][j – 1], d[i + (1 << (j - 1))][j - 1]),

其中1 << (j - 1) 代表2的 j – 1次幂查询操作很简单,

我们要先求出一个数k 让2的k次幂小于等于R-L+1,

那么d[L][k]与d[R-(1 << k) + 1][k]就覆盖了整个L到R的区间,读者可自行验证。

现在就可以写出完整的代码了

#include<stdio.h>
#include<algorithm>
using namespace std;
int a[100];
int dp[100][10];
int query(int L, int R){
	int k = 0;
	while (1 << (k + 1) <= R - L + 1)
		k++;
	return min(dp[L][k], dp[R - (1 << k) + 1][k]);
}
int main(){
	int n, i, j;
	scanf("%d", &n);
	for (i = 1; i <= n; i++){
		scanf_s("%d", &a[i]);
		dp[i][0] = a[i];
	}
	for (i = 1; (1 << i) <= n; i++){
		for (j = 1; j + (1 << (i - 1)) <= n; j++){
			dp[j][i] = min(dp[j][i - 1], dp[j + (1 << (i - 1))][i - 1]);
		}
	}
	int L, R;
	scanf("%d%d", &L, &R);
	printf("%d\n", query(L, R));
	return 0;
}


附上一个相关练习[南阳oj上的一道题 很好](http://acm.nyist.net/JudgeOnline/problem.php?pid=119)

实用数据结构---RMQ问题

标签:数据结构   rmq   算法   sparse-table   区间最值查询   

原文地址:http://blog.csdn.net/u013174702/article/details/44003707

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