士兵杀敌(三)
时间限制: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算法,区间求最值。
但是为了练习一下刚学的线段树,还是勉强用线段树写了,第一次交超时,然后改为位运算,1800多毫秒,勉强通过。
由于需要求出最大和最小值,所以查找函数要定义成结构体,便于一次返回最大值和最小值
代码
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<stdio.h>
#include<queue>
using namespace std;
//线段树基本操作
//建立两个线段树
const int maxn=100005;
int N;//士兵总数
int Q;//查询次数
struct node
{
int left;
int right;
int max_num;
int min_num;
} Tree[maxn*4];
void Build(int root,int star,int end)
{
Tree[root].left=star;
Tree[root].right=end;
if(star==end)
{
scanf("%d",&Tree[root].max_num);
Tree[root].min_num=Tree[root].max_num;
return;
}
int mid=(star+end)>>1;
Build(root<<1,star,mid);
Build(root<<1|1,mid+1,end);
Tree[root].max_num=Tree[root<<1].max_num>Tree[root<<1|1].max_num?Tree[root<<1].max_num:Tree[root<<1|1].max_num;
Tree[root].min_num=Tree[root<<1].min_num<Tree[root<<1|1].min_num?Tree[root<<1].min_num:Tree[root<<1|1].min_num;
}
node Find(int root,int star,int end)
{
if(Tree[root].left==star&&Tree[root].right==end)
return Tree[root];
int mid=(Tree[root].left+Tree[root].right)>>1;
if(end<=mid)
return Find(root<<1,star,end);
else if(star>mid)
return Find(root<<1|1,star,end);
else
{
node flag1=Find(root<<1,star,mid);
node flag2=Find(root<<1|1,mid+1,end);
node flag;
flag.max_num=flag1.max_num>flag2.max_num?flag1.max_num:flag2.max_num;
flag.min_num=flag1.min_num<flag2.min_num?flag1.min_num:flag2.min_num;
return flag;
}
}
int main()
{
scanf("%d%d",&N,&Q);
Build(1,1,N);//建立线段树
int m,n;//查询区间范围
while(Q--)
{
scanf("%d%d",&m,&n);
node temp=Find(1,m,n);
printf("%d\n",temp.max_num-temp.min_num);
}
return 0;
}