士兵杀敌(三)

来源:互联网 发布:主流网管软件都有啥 编辑:程序博客网 时间:2024/06/09 21:20

题目出处

描述

南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比较,计算出两个人的杀敌数差值,用这种方法一方面能鼓舞杀敌数高的人,另一方面也算是批评杀敌数低的人,起到了很好的效果。

所以,南将军经常问军师小工第i号士兵到第j号士兵中,杀敌数最高的人与杀敌数最低的人之间军功差值是多少。

现在,请你写一个程序,帮小工回答南将军每次的询问吧。

注意,南将军可能询问很多次。

输入
只有一组测试数据
第一行是两个整数N,Q,其中N表示士兵的总数。Q表示南将军询问的次数。(1<N<=100000,1<Q<=1000000)
随后的一行有N个整数Vi(0<=Vi<100000000),分别表示每个人的杀敌数。
再之后的Q行,每行有两个正正数m,n,表示南将军询问的是第m号士兵到第n号士兵。
输出
对于每次询问,输出第m号士兵到第n号士兵之间所有士兵杀敌数的最大值与最小值的差。
样例输入
5 21 2 6 9 31 22 4
样例输出
17
#include<cstdio>#include<algorithm>#define maxx 100000using namespace std;#define L o<<1#define R (o<<1)|1int tmax,tmin;//记录最大最小值,减少查询次数 #define INF 0x3f3f3f3f struct Node{int l,r,Max,Min;}Tree[maxx<<2];void PushUp(int o){Tree[o].Max = max(Tree[L].Max,Tree[R].Max);Tree[o].Min = min(Tree[L].Min,Tree[R].Min);}void Build(int o, int l, int r){Tree[o].l=l;Tree[o].r=r;if(l == r){int t;scanf("%d",&t);Tree[o].Min = Tree[o].Max= t;return;}int mid = ( l+r ) >> 1;Build(L,l,mid);Build(R,mid+1,r);PushUp(o);}void QueryMax_Min(int o,int l,int r,int x,int y){if(l==x&&r==y){tmax=max(Tree[o].Max,tmax);tmin=min(Tree[o].Min,tmin);return;}int mid=(l+r)>>1;if(y<=mid)QueryMax_Min(R,l,mid,x,y);else if(x>mid)QueryMax_Min(L,mid+1,r,x,y);else{QueryMax_Min(R,l,mid,x,mid);QueryMax_Min(L,mid+1,r,mid+1,y);}}  int main(){char a[7];int N,M,n,m;scanf("%d%d",&N,&M);Build(1,1,N);while(M--){int x,y;tmax=-INF;tmin=INF;scanf("%d%d",&m,&n);QueryMax_Min(1,1,N,m,n);printf("%d\n",tmax-tmin);}return 0;}
上面这个min 和max是写在一起的,但是要是用下面一个,打死也过不了啊,分开查询会超时

#include<cstdio>#include<algorithm>#define maxx 100000using namespace std;#define L o<<1#define R (o<<1)|1struct Node{int l,r,Max,Min;}Tree[maxx<<2];void PushUp(int o){Tree[o].Max = max(Tree[L].Max,Tree[R].Max);Tree[o].Min = min(Tree[L].Min,Tree[R].Min);}void Build(int o, int l, int r){Tree[o].l=l;Tree[o].r=r;if(l == r){int t;scanf("%d",&t);Tree[o].Min = Tree[o].Max= t;return;}int mid = ( l+r ) >> 1;Build(L,l,mid);Build(R,mid+1,r);PushUp(o);}int QueryMax(int o,int l,int r,int x,int y) //查找x到y的最大值 {if (l == x && r == y){return Tree[o].Max;}int mid = (l + r) / 2;if (mid >= y)return QueryMax(L,l,mid,x,y);else if (x > mid)return QueryMax(R,mid+1,r,x,y);elsereturn max(QueryMax(L,l,mid,x,mid) , QueryMax(R,mid+1,r,mid+1,y));//更新当前节点 }int QueryMin(int o,int l,int r,int x,int y) //查找x到y的最小值 {if (l == x && r == y){return Tree[o].Min;}int mid = (l + r) / 2;if (mid >= y)return QueryMin(L,l,mid,x,y);else if (x > mid)return QueryMin(R,mid+1,r,x,y);elsereturn min(QueryMin(L,l,mid,x,mid) , QueryMin(R,mid+1,r,mid+1,y));//更新当前节点 }int main(){char a[7];int N,M,n,m;scanf("%d%d",&N,&M);Build(1,1,N);while(M--){scanf("%d%d",&m,&n);int ans = QueryMax(1,1,N,m,n) - QueryMin(1,1,N,m,n);printf("%d\n",ans);}return 0;}