NYOJ 题目119 士兵杀敌(三)(线段树,区间最值)

士兵杀敌(三)

时间限制:2000 ms  |  内存限制:65535 KB
难度:5
描述

南将军统率着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 2
1 2 6 9 3
1 2
2 4
样例输出
1
7

还可以用RMQ(目前还不会),

这是线段树做的。。时间空间复杂度大,

注意求最大最小值。。。。

 

 
/********************** 
2013-8-19 18:35:49 
Time: 500MS  Memory: 7180K 
Author: zyh
Status: Accepted
**********************/ 
#define N 100010
#define MAX(a,b) (a)>(b)?(a):(b)
#define MIN(a,b) (a)<(b)?(a):(b)
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>

using namespace std;

struct IntervalTree{
	int  L,R;
	int  max,min;
}tree[N*4];

int aa[N];

void build(int p,int l,int r){
	
	tree[p].L = l; tree[p].R = r;
	tree[p].max = -1;
	tree[p].min = 100000010;
	if(l==r) {
		tree[p].max = aa[l];
		tree[p].min = aa[l];
		return ;
	}
	int mid = (l+r)>>1;
	
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);

	tree[p].max = MAX(tree[p<<1].max,tree[p<<1|1].max);
	tree[p].min = MIN(tree[p<<1].min,tree[p<<1|1].min);
}



int Max,Min;
void query(int  p,int  l,int  r){
	
	if( l == tree[p].L && r == tree[p].R ){
	
		if(tree[p].max>Max) Max = tree[p].max;
		if(tree[p].min<Min) Min = tree[p].min;
		return ;
	}

	int  mid = (tree[p].L + tree[p].R)>>1;
	
	if(r<=mid)	 query(p<<1,l,r);
	else if(l>mid)	query(p<<1|1,l,r);
	else{	
		query(p<<1,l,mid);
		query(p<<1|1,mid+1,r);	
	}
}

int main()
{
	int n,m,i,a,b;	
	char s[2];
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++) scanf("%d",&aa[i]);
	build(1,1,n);

	while(m--){
			scanf("%d%d",&a,&b);
			Min = 100000010; Max = -1;
			query(1,a,b);
			printf("%d\n",Max-Min);//一开始用的longlong输出,“%lld”,后来忘改了,导致WA好几次不解
	}
	
	return 0;
}