RMQ问题

一些废话

难得闲暇的一个周日下午

用了三个小时学了一下 一维和二维的RMQ ,作文以记之  雾) 

正题:

什么是RMQ问题?

        RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题

算法思路:

通过复杂度为O(nlogn)的时间预处理后,以复杂度O(1)找出一段区间内的最大(小)值

预处理

a[i]是原数列的数值

f[i, l]表示从第i个数起连续2^{l}个数中的最大(小)值。

那么初始化的内容就显而易见了:f[i,0]就等于a[i]

在写dp时,回想一下复杂度为nlogn,便知道其中一层循环是2的指数级增长

那么 代码如下

	for(register int i=1;i<=k;i++)
	  for(register int l=1;l<=n;l++)
	    if(l+(1<

上面的k也就是一个2的最大指数,根据题意来定

一般10的6次方k取20刚刚好

查询

求最值并不像求和一样必须是刚刚好组成,而可以有重叠的部分

那么,我们便可以得到

RMQ(l, r)=min(f[l][k],f[r-(1<

这里的k又是什么?????

其实这里的k表示不大于n的2的最大次幂

可以这样求出k

	int k=0;
	while(1<<(k+1)<=r-l+1)k++;

代码

void RMQ(int t){
	for(register int i=1;i<=n;i++)f[i][0]=a[i];
	for(register int i=1;i<=21;i++)
	  for(register int l=1;l<=t;l++)
	    if(l+(1<

例题

P2251 质量检测

就是一个裸的模板

#include
#include
#define maxn 105000
using namespace std;
int a[maxn],f[maxn][22],n,m;
inline int read()
{
    int x=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x*=10,x+=ch-'0',ch=getchar();
    return x;
}
void csh(int t){
	for(register int i=1;i<=n;i++)f[i][0]=a[i];
	for(register int i=1;i<=20;i++)
	  for(register int l=1;l<=t;l++)
	    if(l+(1<>n>>m;
	for(register int i=1;i<=n;i++)a[i]=read();
	csh(n);
	for(register int i=1;i<=n-m+1;i++)
	  cout<

二维RMQ

其实思路是一模一样的

先放一下代码吧 要是懂了一维二维就不难理解

可以试着A一下POJ 2019 Cornfields 

​
#include 
#include 
#include 
#include 
#include 
using namespace std;
int dpi[300][300][9],dpa[300][300][9];
//因为题目中说是正方形,便可以省略一维,最后的9表示编边长为2的几次方;
int main()
{
    int n,b,k,i,j,ii,jj,x,y;
    int maxa,mina;
    scanf("%d%d%d",&n,&b,&k);
    memset(dpi,0,sizeof(dpi));
    memset(dpa,0,sizeof(dpa));
    for(i=0; i

 

你可能感兴趣的:(动态规划,RMQ问题)