RMQ问题

原创 2016年05月31日 09:12:12

RMQ(Range Minimum/Maximum Query)问题是指对于长度为n的数列weight,回答若干询问RMQ(weight,l,r)(l,r<=n),返回数列A中下标在i,j里的最小(大)值。
假设询问m次,如果对于每个询问都扫描对应的区间,找到最值,那么最坏情况和平均情况下都是O(nm)的时间复杂度。所以需要事先进行一些预处理,使得一些重复计算的东西不再重复计算,才能够将复杂度降低下来。如果先预先计算一些区间的最值,然后把每个询问都拆成若干个计算了最值的区间并统计这些区间的最值的最值,就可以得出答案。根据二分法的思想,将统计的区间规定为所有长度为2的非负整数次幂的区间。用rmq[i][j]表示从第i个数开始后面2^j个数的最值,很显然rmq[i][0]等于weight[i],j的最大值为(int)((log(N))/(log(2.0)))。递推关系为rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1])。可以看到,这是一个动态规划问题。对于每一次询问,j的最大值mi只能取(int)((log(r-l+1))/(log(2.0)))。为了防止超出边界,答案应该写成min(rmq[l][mi],rmq[r-(1<<mi)+1][mi])而不是min(rmq[l][mi],rmq[l+(1<<mi)][mi])。
以hihoCoder1068为例给出代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>  
#include<algorithm>  
using namespace std;    
const int maxn=1e6+5;  
const int max_pos=20;  
struct Quary
{
	int l,r; 
}quary[maxn];   
int N,Q;  
int weight[maxn];  
int rmq[maxn][max_pos];   

int main()
{  
	scanf("%d",&N);  
    for(int i=1;i<=N;i++) scanf("%d",&weight[i]);  
    scanf("%d",&Q);
    for(int i=1;i<=Q;i++) scanf("%d%d",&quary[i].l,&quary[i].r);    
	memset(rmq,0x5f,sizeof(rmq)); 
  	for(int i=1;i<=N;i++) rmq[i][0]=weight[i];   
    int l=(int)((log(N))/(log(2.0)));  
    for(int j=1;j<=l;j++)
	{  
        for(int i=1;i+(1<<j)-1<=N;i++)
		{  
            rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]);  
        }  
    } 
    for(int i=1;i<=Q;i++)
	{  
        int l=quary[i].l;  
        int r=quary[i].r;  
        int mi=(int)((log(r-l+1))/(log(2.0)));  
        printf("%d\n",min(rmq[l][mi],rmq[r-(1<<mi)+1][mi]));  
    }  
}


理解RMQ问题和ST算法的原理

1.RMQ问题     RMQ (Range Minimum/Maximum Query):对于长度为n的数组A,回答若干询问RMQ(A,i,j)(i,jRMQ问题是指求区间最值的问题。最简单的方法...
  • aitangyong
  • aitangyong
  • 2014年05月25日 13:16
  • 1192

关于RMQ问题的一些感悟

根据询问,修改,单点,区间,在线,离线的各种组合大概有8类问题吧。 一般就是4种解决办法吧。 1、线段树 2、树状数组 3、ST表 4、差分 线段树的话是最万能的方法了...
  • xl2015190026
  • xl2015190026
  • 2017年03月07日 15:57
  • 600

RMQ问题的线段树解法

RMQ(Range Minimum Query)问题是计算一个输入数列A[0...n-1]从位置i到位置j之间的最小值,即RMQ[i,j]=min{A[k], k=i,i+1...j}。RMQ的解法有...
  • ljsspace
  • ljsspace
  • 2011年08月02日 19:09
  • 2797

poj3693——后缀数组+RMQ

还是后缀数组,我觉得用后缀数组做字符串的题真真无敌了,今天做字符串练习时,又学到一项新技能,RMQ,加上题目的思路比较巧,就随意做一下总结。。 题目链接:http://poj.org/pro...
  • ZouCharming
  • ZouCharming
  • 2015年06月30日 20:00
  • 418

RMQ算法分析

RMQ算法,是一个快速求区间最值的离线算法,预处理时间复杂度O(n*log(n)),查询O(1),所以是一个很快速的算法,当然这个问题用线段树同样能够解决。 问题:给出n个数ai,让你快速查询某个...
  • y990041769
  • y990041769
  • 2014年08月06日 18:48
  • 5431

RMQ学习总结(附带简单例题)

RMQ (Range Minimum/Maximum Query)问题 含义:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j,返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ...
  • Cynthia_wjyi
  • Cynthia_wjyi
  • 2015年08月07日 18:11
  • 1350

RMQ算法 快速求区间最大最小值

RMQ基本上就是来求区间嘴子问题的 maxsum【i】【j】表示从数字num【】下表i开始的后1 开始初始化两个数组         for(i=1;i         {         ...
  • zxf654073270
  • zxf654073270
  • 2015年08月10日 15:13
  • 669

C++的RMQ的代码实现

/* 1.dp[i][j]表示从i开始长为2的j次方的数组长度,所以他是a[i]~a[i+2^j-1]的数组里的最值。 2.i...
  • m0_37833525
  • m0_37833525
  • 2017年05月29日 17:05
  • 249

Sparse Table算法 - RMQ问题的简单高效算法

Sparse Table算法是用来解决一类RMQ问题的O(nlog2n)的算法,而且代码非常好写,在本质上是一个动态规划,写起来其实也就是几十行。那么在这里的RMQ问题是什么呢?RMQ问题,中文名应该...
  • WenDavidOI
  • WenDavidOI
  • 2016年02月15日 19:36
  • 308

RMQ(模板 ST 区间最值,区间频繁次数)

RMQ(模板 ST 区间最值,区间频繁次数)
  • u012860063
  • u012860063
  • 2014年11月03日 22:36
  • 1552
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:RMQ问题
举报原因:
原因补充:

(最多只允许输入30个字)