RMQ 模板

RMQ定义:输入N个数和M次询问,每次询问一个区间[L,R],求第L个数到R个数之间的最大值。
RMQ原理:A[1..N]表示一组数,F[I,J]表示从A[I]到A[I+2^J-1]这个范围内的最大值,也就是以A[I]为起点连续2^J个数的最大值,由于元素个数为2^J个,所以从中间平均分成两部分,每一部分的元素个数刚好为2^(J-1)个,动态规划;
思路:
•整个区间的最大值一定是左右两部分最大值的较大值,满足动态规划的最优原理
•状态转移方程:
•F[I,J]=max(F[I,J-1],F[I+2^(J-1),J-1])
•边界条件为F[I,0]=A[I]
这样就可以在O(NlgN)的时间复杂度内预处理F数组。
一维RMQ模板

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
#define N 50005
int dpmin[N][20], dpmax[N][20];
int main()
{
	int i, j, n, m;
	scanf("%d %d", &n, &m);
	memset(dpmin, 0, sizeof(dpmin));
	memset(dpmax, 0, sizeof(dpmax));
	for(i=1; i<=n; i++)
	{
		scanf("%d", &dpmin[i][0]);
		dpmax[i][0]=dpmin[i][0];
	}
	int mm=floor(log(1.0*n)/log(2.0));
	for(j=1; j<=mm; j++)
		for(i=1; i<=n; i++)
		{
			if((i+(1<<(j-1)))<=n)
			{
				dpmin[i][j]=min(dpmin[i][j-1], dpmin[i+(1<<(j-1))][j-1]);
				dpmax[i][j]=max(dpmax[i][j-1], dpmax[i+(1<<(j-1))][j-1]);
			}
		}
	int x, y;
	for(int i=1; i<=m; i++)
	{
		scanf("%d %d", &x, &y);
		int  mid=floor(log(y*1.0-x+1)/log(2.0));
		int maxnum=max(dpmax[x][mid], dpmax[y-(1<<mid)+1][mid]);
		int minnum=min(dpmin[x][mid], dpmin[y-(1<<mid)+1][mid]);
		printf("%d\n", maxnum-minnum);
	}
	return 0;
}
二维
void makermq(int n,int m,int b[maxn][maxn])
{
    int row,col,i,j;
    for(row=1; row<=n; row++)
        for(col=1; col<=m; col++)
            dp2[row][col][0][0]=b[row][col];
    for(i=0; (1<<i)<=n; i++)
        for(j=0; (1<<j)<=m; j++)
        {
            if(i==0&&j==0) continue;
            for(row=1; row+(1<<i)-1<=n; row++)
                for(col=1; col+(1<<j)-1<=m; col++)
                {
                    if(i==0)
                        dp2[row][col][i][j]=max(dp2[row][col][i][j-1],dp2[row][col+(1<<(j-1))][i][j-1]);
                    else
                        dp2[row][col][i][j]=max(dp2[row][col][i-1][j],dp2[row+(1<<(i-1))][col][i-1][j]);
                }
        }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值