题目描述
农夫约翰的 N (1 ≤ N ≤ 50,000)头奶牛,每天挤奶时总会按同样的顺序站好。一日,农夫约翰决定为奶牛们举行一个“终极飞盘”比赛。为简化问题,他将从奶牛队列中选出一个连续区间来进行游戏。不过,参加游戏的奶牛要玩的开心的话就不能在身高上差距太大。农夫约翰制定了 Q (1 ≤ Q ≤ 200,000) 个预定的参赛组,给出它们的身高 (1 ≤ 身高 ≤ 1,000,000)。对每个参赛组,他需要你帮助确定组中最高牛和最低牛的身高差。
输入格式
第 1 行: 两个空格隔开的整数,N 和 Q。
第 2..N+1 行: 第 i+1 行包含一个整数表示第 i 头牛的身高。
第 N+2..N+Q+1 行: 两个整数 A 和 B(1 ≤ A ≤ B ≤ N),表示一个从 A 到 B 的参赛组区间。
输出格式
第 1..Q 行: 每行包含一个整数来表示区间上最大身高差。
样例输入
6 3
1
7
3
4
2
5
1 5
4 6
2 2
样例输出
6
3
0
为了训练一下线段树而写的模板题。
教训:一定要算好内存,开数组要记得两倍!!(一开始数组开小导致爆了)
#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define MAXX 1100000
using namespace std;
int a[51000];
int n,m;
struct data{
int ma,mi;
}num[1100000];
void read(int &x)
{
char t=getchar();x=0;int f=1;
while((t<48)or(t>57)){if(t=='-')f=-1;t=getchar();}
while((t>=48)and(t<=57)){x=x*10+t-48;t=getchar();}
x*=f;
}
void updata(int now)
{
num[now].ma=max(num[now<<1].ma,num[(now<<1)+1].ma);
num[now].mi=min(num[now<<1].mi,num[(now<<1)+1].mi);
}
void build(int now,int l,int r)
{
if (l==r)
{
num[now].ma=a[l];
num[now].mi=a[l];
return;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build((now<<1)+1,mid+1,r);
updata(now);
}
data query(int now,int l,int r,int lrange,int rrange)
{
data t;
if ((lrange<=l)and(r<=rrange))
{
t.ma=num[now].ma;
t.mi=num[now].mi;
return t;
}
int mid=(l+r)>>1;
data t1,t2;
if (lrange<=mid) t1=query(now<<1,l,mid,lrange,rrange);
else t1.ma=0,t1.mi=MAXX;
if (mid<rrange) t2=query((now<<1)+1,mid+1,r,lrange,rrange);
else t2.ma=0,t2.mi=MAXX;
t.ma=max(t1.ma,t2.ma);
t.mi=min(t1.mi,t2.mi);
return t;
}
int main()
{
freopen("lineup.in","r",stdin);
freopen("lineup.out","w",stdout);
read(n),read(m);
for (int i=1;i<=n;++i) read(a[i]);
build(1,1,n);
for (int i=1;i<=m;++i)
{
int x,y;
read(x),read(y);
data ans=query(1,1,n,x,y);
printf("%d\n",ans.ma-ans.mi);
}
return 0;
}