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\n",query1(1,n,1)-query2(1,n,1)); 40 } 41 } 42 return 0; 43 }