goj 最值差(线段树区间查询最值)

Problem Description:

给定N个数A1A2A3A4...AN.求任意区间Ai到Aj中的最大数与最小数之差。

Input:

输入包含多组测试,每组测试的第一行是两个数N(1<=N<=50000)和M(1<=M<=100000),第二行是N个数A1到AN(1<=Ai<=10000);接下来M行输入M个询问,每个询问包含两个数Ai,Aj。

Output:

对于每组测试,输出每个询问的答案。

Sample Input:

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

Sample Output:

6
3
0
解题思路:基本操作:线段树区间查询最值,时间复杂度大概为O(nlogn)。
AC代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=50005;
 4 int a,b,n,m,s[maxn];
 5 struct NODE{int maxval,minval;}t[maxn<<2];
 6 void build(int l,int r,int x){//建树
 7     int mid=(l+r)>>1;
 8     if(l==r){t[x].maxval=t[x].minval=s[mid];return;}
 9     build(l,mid,x<<1);
10     build(mid+1,r,x<<1|1);
11     t[x].maxval=max(t[x<<1].maxval,t[x<<1|1].maxval);//父节点的值为左右孩子的最大值
12     t[x].minval=min(t[x<<1].minval,t[x<<1|1].minval);//父节点的值为左右孩子的最小值
13 }
14 int query1(int l,int r,int x){//查询区间最大值
15     if(a<=l&&b>=r)return t[x].maxval;
16     else{
17         int mid=(l+r)>>1;
18         if(b<=mid)return query1(l,mid,x<<1);
19         else if(a>mid)return query1(mid+1,r,x<<1|1);
20         else return max(query1(l,mid,x<<1),query1(mid+1,r,x<<1|1));
21     }
22 }
23 int query2(int l,int r,int x){//查询区间最小值
24     if(a<=l&&b>=r)return t[x].minval;
25     else{
26         int mid=(l+r)>>1;
27         if(b<=mid)return query2(l,mid,x<<1);
28         else if(a>mid)return query2(mid+1,r,x<<1|1);
29         else return min(query2(l,mid,x<<1),query2(mid+1,r,x<<1|1));
30     }
31 }
32 int main(){
33     while(~scanf("%d %d",&n,&m)){
34         for(int i=1;i<=n;++i)scanf("%d",&s[i]);
35         memset(t,0,sizeof(t));//清0
36         build(1,n,1);//建树
37         while(m--){
38             scanf("%d %d",&a,&b);
39             printf("%d
",query1(1,n,1)-query2(1,n,1));
40         }
41     }
42     return 0;
43 }
原文地址:https://www.cnblogs.com/acgoto/p/9267744.html