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;
}