Balanced Lineup(RMQ)

Balanced Lineup(RMQ)

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

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

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

样例
Input

6 3
1
7
3
4
2
5
1 5
4 6
2 2

Output
6
3
0

数据范围与提示
对于全部数据,1≤N≤5×104,1≤Q≤1.8×105,1≤h i≤106,1≤A≤B≤N。

思路: RMQ的板,也可以用线段树来做,这里主要记录一下RMQ的板

AC代码:

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int N=1e6+10,M=20;
int a[N],f[N][M],d[N][M];
//f[i][j]记录从i开始,长度为2^j的最大值
//d[i][j]同上记录最小值
int n,q;
void init()
{
	int i,j;
	for(j=0;(1<<j)<=n;j++)//x<<1,表示x*2,故1<<j表示1*2^j,即2^j,循环表示所计算长度不能超过总长度
	{
		for(i=1;i+(1<<j)-1<=n;i++)//表示右端点不能超过所给最后一个端点
		{
			if(!j)//当长度为1时,最大值和最小值都是其本身
			f[i][j]=a[i],d[i][j]=a[i];
			else
			{//分成长度相等的两部分,区间不可重复
				f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
				d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
			}
		}
	}
}
void query(int l,int r)
{
	int len=r-l+1;//区间总长度
	int k=log(len)/log(2);//此时区间可重复,每部分长度最大为2^k,则2^k<=len,
	int maxx=max(f[l][k],f[r-(1<<k)+1][k]);
	int minn=min(d[l][k],d[r-(1<<k)+1][k]);
	printf("%d\n",maxx-minn);
}
int main()
{
	int i,j,k;
	scanf("%d%d",&n,&q);
	for(i=1;i<=n;i++)
	scanf("%d",&a[i]);
	init();//预处理
	while(q--)
	{
		int l,r;
		scanf("%d%d",&l,&r);
		query(l,r);//查询
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值