1. 概述

RMQ(Range Minimum/Maximum Query)。即区间最值查询,是指这样一个问题:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间的最小/大值。

这两个问题是在实际应用中常常遇到的问题。以下介绍一下解决这两种问题的比較高效的算法。当然,该问题也能够用线段树(也叫区间树)解决,算法复杂度为:O(N)~O(logN),这里我们暂不介绍。

2.RMQ算法

对于该问题,最easy想到的解决方式是遍历,复杂度是O(n)。但当数据量非常大且查询非常频繁时。该算法无法在有效的时间内查询出正解。

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

(一)首先是预处理,用动态规划(DP)解决。

设A[i]是要求区间最值的数列。F[i, j]表示从第i个数起连续2^j个数中的最大值。(DP的状态)

比如:

A数列为:3 2 4 5 6 8 1 2 9 7

F[1,0]表示第1个数起,长度为2^0=1的最大值,事实上就是3这个数。

同理 F[1,1] = max(3,2) = 3, F[1,2]=max(3,2,4,5) = 5,F[1,3] = max(3,2,4,5,6,8,1,2) = 8;

而且我们能够easy的看出F[i,0]就等于A[i]。(DP的初始值)

这样。DP的状态、初值都已经有了,剩下的就是状态转移方程。

我们把F[i。j]平均分成两段(由于f[i,j]一定是偶数个数字)。从 i 到i + 2 ^ (j - 1) - 1为一段。i + 2 ^ (j - 1)到i + 2 ^ j - 1为一段(长度都为2 ^ (j - 1))。

用上例说明,当i=1。j=3时就是3,2,4,5 和 6,8,1,2这两段。

F[i,j]就是这两段各自最大值中的最大值。于是我们得到了状态转移方程F[i, j]=max(F[i,j-1],
F[i + 2^(j-1),j-1])。

代码例如以下:

    void RMQ(int num) //预处理->O(nlogn)
{
for(int j = 1; j < 20; ++j)
for(int i = 1; i <= num; ++i)
if(i + (1 << j) - 1 <= num)
{
maxsum[i][j] = max(maxsum[i][j - 1], maxsum[i + (1 << (j - 1))][j - 1]);
minsum[i][j] = min(minsum[i][j - 1], minsum[i + (1 << (j - 1))][j - 1]);
}
}

这里我们须要注意的是循环的顺序。我们发现外层是j,内层所i,这是为什么呢?能够是i在外,j在内吗?

答案是不能够。由于我们须要理解这个状态转移方程的意义。

状态转移方程的含义是:先更新全部长度为F[i,0]即1个元素,然后通过2个1个元素的最值,获得全部长度为F[i,1]即2个元素的最值,然后再通过2个2个元素的最值。获得全部长度为F[i,2]即4个元素的最值,以此类推更新全部长度的最值。

而假设是i在外,j在内的话,我们更新的顺序就是F[1,0],F[1,1],F[1,2],F[1,3],表示更新从1開始1个元素。2个元素,4个元素,8个元素(A[0],A[1],....A[7])的最值。这里F[1,3] = max(max(A[0],A[1],A[2],A[3]),max(A[4],A[5],A[6],A[7]))的值。可是我们根本没有计算max(A[0],A[1],A[2],A[3])和max(A[4],A[5],A[6],A[7]),所以这个方案肯定是错误的。

为了避免这种错误,一定要好好理解这个状态转移方程所代表的含义。





(二)然后是查询。

假如我们须要查询的区间为(i,j),那么我们须要找到覆盖这个闭区间(左边界取i。右边界取j)的最小幂(能够反复。比方查询5,6。7,8,9,我们能够查询5678和6789)。

由于这个区间的长度为j - i + 1,所以我们能够取k=log2( j - i + 1)。则有:RMQ(A, i, j)=max{F[i , k], F[ j - 2 ^ k + 1, k]}。

举例说明。要求区间[2,8]的最大值,k = log2(8 - 2 + 1)= 2,即求max(F[2, 2],F[8 - 2 ^ 2 + 1, 2]) = max(F[2, 2],F[5, 2])。

在这里我们也须要注意一个地方。就是<<运算符和+-运算符的优先级。

比方这个表达式:5 - 1 << 2是多少?

答案是:4 * 2 * 2 = 16。

所以我们要写成5 - (1 << 2)才是5-1 * 2 * 2 = 1。

RMQ 算法入门的更多相关文章

  1. 线段树:CDOJ1591-An easy problem A (RMQ算法和最简单的线段树模板)

    An easy problem A Time Limit: 1000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  2. 【转】 SVM算法入门

    课程文本分类project SVM算法入门 转自:http://www.blogjava.net/zhenandaci/category/31868.html (一)SVM的简介 支持向量机(Supp ...

  3. 三角函数计算,Cordic 算法入门

    [-] 三角函数计算Cordic 算法入门 从二分查找法说起 减少乘法运算 消除乘法运算 三角函数计算,Cordic 算法入门 三角函数的计算是个复杂的主题,有计算机之前,人们通常通过查找三角函数表来 ...

  4. 循环冗余校验(CRC)算法入门引导

    目录 写给嵌入式程序员的循环冗余校验CRC算法入门引导 前言 从奇偶校验说起 累加和校验 初识 CRC 算法 CRC算法的编程实现 前言 CRC校验(循环冗余校验)是数据通讯中最常采用的校验方式.在嵌 ...

  5. 【算法入门】广度/宽度优先搜索(BFS)

    广度/宽度优先搜索(BFS) [算法入门] 1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较 ...

  6. RMQ算法讲解

    RMQ算法 引入: 例1.题目描述 输入N个数和M次询问,每次询问一个区间[L,R],求第L个数到R个数之间的最大值.   第一种方法:大暴力之术. 但是……时间复杂度最坏会达到 $O(NM)$,一半 ...

  7. (转)三角函数计算,Cordic 算法入门

    由于最近要使用atan2函数,但是时间上消耗比较多,因而网上搜了一下简化的算法. 原帖地址:http://blog.csdn.net/liyuanbhu/article/details/8458769 ...

  8. 【转】循环冗余校验(CRC)算法入门引导

    原文地址:循环冗余校验(CRC)算法入门引导 参考地址:https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks#Re ...

  9. LDA算法入门

    http://blog.csdn.net/warmyellow/article/details/5454943 LDA算法入门 一. LDA算法概述: 线性判别式分析(Linear Discrimin ...

随机推荐

  1. [BZOJ4710][JSOI2011]分特产(组合数+容斥原理)

    4710: [Jsoi2011]分特产 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 395  Solved: 262[Submit][Status] ...

  2. 【线段树】hdu6183 Color it

    题意: 维护一个数据结构,支持三种操作: ①在平面上(x,y)处添加一个颜色为c的点. ②询问平面上(1,y1)-(x,y2)范围内,有多少种不同颜色的点. ③清除平面上所有点. 颜色数量很少,对于每 ...

  3. 慢查询(找出mysql中超时的select语句)

    第一步:进入mysql界面 //查询多少秒 才属于慢查询. show variables like ‘long_query_time’ ; 第二步: //更改这个时间值  如:select语句执行超过 ...

  4. all objects of the same class share the same set of class methods

    #include <iostream> #include "First.h" void Test(); int main() { std::cerr<<&q ...

  5. js中getBoundingClientRect()的用法介绍

    平时经常获取一个div的位置,用了定位,取位置还好,在不用定位的情况下,计算一个div在页面的距离,就可以用到getBoundingClientRect()方法. getBoundingClientR ...

  6. [转] Download Images from Multiple Maps

    转载自 李旭, Tool: Download Images from Multiple Maps Summary SAS Planet是一款俄罗斯绿色免费软件,一直持续不断更新.该软件最大的一个特点就 ...

  7. 【c3p0】报错:java.io.FileNotFoundException: Resource not found at path '/mchange-log.properties'

    配置项目启动初始,报错如下: java.io.FileNotFoundException: Resource not found at path '/mchange-commons.propertie ...

  8. google的开源项目总结

    转自http://www.feng5166.com/blog/424.html google的开源项目值得我们一用的,这些项目很有意义,甚至可以直接用在我们自己的工作上!学习编程的的一个比较好的方式就 ...

  9. JAVA常见算法题(三十)

    package com.forezp.util; import java.io.BufferedReader; import java.io.FileReader; import java.io.In ...

  10. 如何在windows下的Python开发工具IDLE里安装其他模块

    以安装Httplib2模块为例 1 下载模块 到 “https://code.google.com/p/httplib2/” 下载一款适合你的压缩包“httplib2-0.4.0.zip” 2 解压下 ...