RMQ算法详解

来源:互联网 发布:淘宝网李小璐同款皮鞋 编辑:程序博客网 时间:2024/05/10 01:33

RMQ算法详解

1. 概述

RMQ(Range Minimum/Maximum Query)即区间最优查询,给定区间长度为n的数列A[],对于查询Q(A,i,j)即回答从i—j区间间的最大值或最小值,解决这个问题一般采用的方法是遍历,遍历的时间复杂度是O(N),如果区间长度够长,每次回答的查询都要遍历,显然没有必要。

2. RMQ算法

本节介绍了一种比较高效的在线算法(ST算法)解决这个问题。所谓在线算法,是指用户每输入一个查询便马上处理一个查询。该算法一般用较长的时间做预处理,待信息充足以后便可以用较少的时间回答每个查询。ST(Sparse Table)算法是一个非常有名的在线处理RMQ问题的算法,它可以在O(nlogn)时间内进行预处理,然后在O(1)时间内回答每个查询。

2. 算法过程

记maxs[i][j]、mins[i][j]表示从i开始连续2^j个数之间的最大值和最小值,利用动态规划的思想,maxs[i][j]可以划分为两部分求解,一部分是i — 2^(j-1),一部分是从i+2^(j-1) — i+2^j,因此maxs[i][j] = max(maxs[i][j-1],maxs[i + (1<<(j-1))][j-1]),同理mins[i][j] = min(maxs[i][j-1],maxs[i + (1<<(j-1))][j-1])
构建maxs的代码如下:

/**m的最大值**/int m = (int) (Math.log(1.0 * a.length) / Math.log(1.0 * 2));/**外从循环表示长度为2^m**/for (int k = 1; k <= m; k++) {    for (int c = 0; c <= a.length; c++) {        if (c + (1 << k) <= a.length) {            dp[c][k] = Math.max(dp[c][k - 1], dp[c + (1 << (k - 1))][k - 1]);        }    }}

3. 查询过程

假设现在查询RMQ(A,i,j),i到j的区间长度为len = i - j + 1 , 记k=log2( j - i + 1),则有:RMQ(A, i, j)=max{ dp[i , k] , dp[ j - 2 ^ k + 1, k] }
查询过程代码如下:

public int getMax(int i, int j) {        int k = (int) (Math.log((j - i + 1) * 1.0) / Math.log(2.0));        return Math.max(dp[i][k], dp[j - (1 << k) + 1][k]);}

4. 典型例题

3.1 poj 3264 Balanced Lineup
题目大意:给出一串的数字,然后给出一个区间a b,输出从a到b的最大的数和最小的数的差
3.2 http://acm.nyist.net/JudgeOnline/problem.php?pid=119
南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比较,计算出两个人的杀敌数差值,用这种方法一方面能鼓舞杀敌数高的人,另一方面也算是批评杀敌数低的人,起到了很好的效果。所以,南将军经常问军师小工第i号士兵到第j号士兵中,杀敌数最高的人与杀敌数最低的人之间军功差值是多少。现在,请你写一个程序,帮小工回答南将军每次的询问吧。

0 0