RMQ——区间最值

概念:
RMQ指的是Range Minimum/Maximum Query 即为区间最值问题。
优点:
此问题放眼看去似乎是一个比较简单的问题,我们可以直接朴素算法走一遍区间,找到最值即可,但是这样的话时间复杂度为O(n2)
如果题目中所给的有多个询问,这时候我们如果还坚持朴素算法的话,必然会超时。这时候RMQ算法的优势就体现出来了

初始化需要的时间复杂度接近O(nlogn),但是查询的时间复杂度为O(1)

递推:
(1)思想:
要从小区间递推到大区间,我们这里采用了分割的方式,也就是先找 [a,a+2^0 -1] 的最值,然后再找 [a + 2^0 ,a + 2^0 + 2 ^0 - 1],这里我们列举的是初始区间,然后这两个区间合并成大区间[a,a + 2^0 + 2 ^0 - 1]。
(2)关系:

dp[i][j] = max(dp[i][j-1],dp[i + (1 << (j -1))][j - 1])
dp[i][j]:以i为起点,区间长度为2^j时的区间最值

例题:Balanced Lineup

FJ 的 NN 头牛总是按同一序列排队。有一天,FJ 决定让一些牛玩一场飞盘比赛。他准备找一群在对列中为置连续的牛来进行比赛,但是为了避免水平悬殊,牛的身高不应该相差太大。FJ 准备了 QQ
个可能的牛的选择和所有牛的身高。他想知道每一组里面最高和最低的牛的身高差别。

输入格式
第一行:N 和 Q; 第二至第 N+1行,第 i+1 行是第 i 头牛的身高 h_ih i ​ ;
第 N+2N+2 至第 N+Q+1 行,每行两个整数 A 和 B,表示从 A 到 B 的所有牛。

输出格式
第一至第 Q 行,每行一个整数,表示对于询问的回答(即最高和最低的牛的身高差)。

RMQ 模板,同时拥有最大值和最小值的求解

#include<iostream>
using namespace std;

const int N=5e4+10,logN=20;

int mi[N][logN+5],mx[N][logN+5],log[N];
int n,m;

int main()
{
	ios::sync_with_stdio(0);
	
	cin>>n>>m;log[0]=-1;
	for(int i=1;i<=n;i++)
	{
		int a;
		cin>>a;
		mi[i][0]=mx[i][0]=a;
		log[i]=log[i>>1]+1;//最大<=长度i的2的次方数
	}
	for(int j=1;j<logN;j++)//枚举区间长度
		for(int i=1;i+(1<<j)-1<=n;i++)//枚举区间左端点
			mi[i][j]=min(mi[i][j-1],mi[i+(1<<j-1)][j-1]),
			mx[i][j]=max(mx[i][j-1],mx[i+(1<<j-1)][j-1]);
	while(m--)
	{
		int l,r;
		cin>>l>>r;
		int s=log[r-l+1];
		cout<<max(mx[l][s],mx[r-(1<<s)+1][s])-min(mi[l][s],mi[r-(1<<s)+1][s])<<endl;
		//把当前区间分为【l,l+2^k】和【r-2^k+1,r】两区间
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红和黑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值