每天挤奶,农夫约翰的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
题目大意:给定n,q分别表示区间的大小为:n,后跟着q次查询;求得给定区间最大值与最小值之差,
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0xffffff0; //确定一个最大值
const int maxn=50010; //n的最大值
/**结点结构*/
struct Node
{
int L,R;
int minV,maxV;
};
Node tree[4*maxn]; //用数组表示线段树
int a[maxn]; //存放结点数值
int maxV=-INF;
int minV=INF; //存放最大值与最小值
/**建立线段树,并赋初值*/
void build_Tree(int root,int L,int R)
{
tree[root].L=L;
tree[root].R=R;
/**到叶子结点时附值*/
if(L==R)
{
tree[root].maxV=tree[root].minV=a[L];
return ;
}
int mid=(tree[root].L+tree[root].R)/2;
build_Tree(2*root,L,mid);
build_Tree(2*root+1,mid+1,R);
tree[root].minV=min(tree[2*root].minV,tree[2*root+1].minV);
tree[root].maxV=max(tree[2*root].maxV,tree[2*root+1].maxV); //当不是叶子结点时,存放左右孩子的最大值与最小值
}
/**查询区间[s,e]中的最大值与最小值*/
void Query(int root,int s,int e)
{
if(minV<=tree[root].minV&&maxV>=tree[root].maxV)
return;
/**当刚好区间相等时*/
if(tree[root].L==s&&tree[root].R==e)
{
minV=min(minV,tree[root].minV);
maxV=max(maxV,tree[root].maxV);
return ;
}
int mid=(tree[root].L+tree[root].R)/2;
/**区间过大时*/
if(e<=mid)
Query(2*root,s,e);
else if(s>mid)
Query(2*root+1,s,e);
/**左右孩子*/
else
{
Query(2*root,s,mid);
Query(2*root+1,mid+1,e);
}
}
int main()
{
int n,q;
int num;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build_Tree(1,1,n);
int s,e;
for(int i=1;i<=q;i++)
{
minV=INF;
maxV=-INF;
scanf("%d%d",&s,&e);
Query(1,s,e);
printf("%d\n",maxV-minV);
}
return 0;
}