Problem Description
题意很简单,给出一个数目为n的非有序序列,然后有m次查询.对于每次查询输入两个正整数l,r请输出区间[l,r]的最大值与最小值的差值
Input
第一行:输入两个正整数n,m (1<=n<=50000, 1<=m<=200000 );
第二行:输入n个整数 大小范围为[1,100000];
接下来的m行,每次两个正整数l,r (1<=l<=r<=n);
Output
输出区间[l,r]最大值与最小值的差值.
Sample Input
6 3
1
7
3
4
2
5
1 5
4 6
2 2
Sample Output
6
3
0
#include<bits/stdc++.h>
using namespace std;
struct node
{
long long mindata;
long long maxdata;
};
struct node tree[200010];
int Min(int a, int b)
{
if(a<b) return a;
else return b;
}
int Max(int a, int b)
{
if(a<b) return b;
else return a;
}
void build(int root, int l, int r)
{
if(l == r)
{
scanf("%lld", &tree[root].mindata);//直到区间为一个下标的时候
tree[root].maxdata = tree[root].mindata;
return ;
}
int mid = (l+r)/2;
build(2*root, l, mid);
build(2*root+1, mid+1, r);
tree[root].maxdata = Max(tree[2*root].maxdata, tree[2*root+1].maxdata);//求最大,更新父亲的值
tree[root].mindata = Min(tree[2*root].mindata, tree[2*root+1].mindata);
}
long long int querymax(int a, int b, int root, int l, int r)//求a,b区间内最大的值
{
if(a <= l && b >= r) //如果l,r满足区间a, b返回l,r区间内最大值
return tree[root].maxdata;
int mid = (l+r)/2;
int red = -100055;
if(a <= mid) red = Max(red, querymax(a, b, 2*root, l, mid));//区间包括了左边,左边递归找最大
if(b > mid) red = Max(red, querymax(a, b, 2*root+1, mid+1, r));
return red;
}
long long int querymin(int a, int b, int root, int l, int r)//求a,b区间内最小的值
{
if(a <= l && b >= r) //如果l,r满足区间a, b返回l,r区间内最小值
return tree[root].mindata;
int mid = (r+l)/2;
long long int red = 100055;
if(a <= mid) red = Min(red, querymin(a, b, 2*root, l, mid));//区间包括了左边,左边递归找最小
if(b > mid) red = Min(red, querymin(a, b, 2*root+1, mid+1, r));
return red;
}
int main()
{
int n, m, l, r;
while(~scanf("%d%d", &n, &m))
{
build(1, 1, n);//从1-n下标构建线段树
while(m--)
{
scanf("%d%d", &l, &r);
printf("%lld\n", querymax(l, r, 1, 1, n)-querymin(l, r, 1, 1, n));
}
}
}