士兵杀敌(三)
时间限制:
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
-
只有一组测试数据
求解区间最值的ST算法点击打开链接
#include<cstdio>
#include<cmath>
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
int dp_max[100005][20];
int dp_min[100005][20];
void RMQ(int n)
{
for(int j=1;j<20;j++)
{
for(int i=1;i<=n;i++)
{
if(i+(1<<j)-1<=n)
{
dp_max[i][j]=MAX(dp_max[i][j-1],dp_max[i+(1<<(j-1))][j-1]);
dp_min[i][j]=MIN(dp_min[i][j-1],dp_min[i+(1<<(j-1))][j-1]);
}
}
}
}
int main()
{
int N,Q,m,n;
while(~scanf("%d%d",&N,&Q))
{
for(int i=1;i<=N;i++)
{
scanf("%d",&dp_max[i][0]);
dp_min[i][0]=dp_max[i][0];
}
RMQ(N);
for(int rie=0;rie<Q;rie++)
{
scanf("%d%d",&m,&n);
int eLog=(int)(log(n-m+1)/log(2));
int a=MAX(dp_max[m][eLog],dp_max[n-(1<<eLog)+1][eLog]);
int b=MIN(dp_min[m][eLog],dp_min[n-(1<<eLog)+1][eLog]);
printf("%d\n",a-b);
}
}
return 0;
}
也可以用线段树的知识求解,参考代码如下
#include <iostream>
#include<algorithm>
#include <cstdio>
#include <cstring>
#define MAXN 1000100
using namespace std;
int array[MAXN];
int Max, Min; //利用全局变量来获取递归结果
typedef struct info{
int Max, Min;
}info;
info segT[MAXN * 4 + 10];
void build(int node, int begin, int end) {
if(begin == end) {
segT[node].Max = segT[node].Min = array[begin];
}
else {
build(node * 2, begin, (begin + end) / 2);
build(node * 2 + 1, (begin + end) / 2 + 1, end);
segT[node].Max = max(segT[node * 2].Max, segT[node * 2 + 1].Max);
segT[node].Min = min(segT[node * 2].Min, segT[node * 2 + 1].Min);
}
}
void query(int node, int begin, int end, int l, int r) {
if(begin == l && end == r) {
Max = max(Max,segT[node].Max);
Min = min(Min,segT[node].Min);
}
else {
int mid = (begin + end) / 2;
if(r <= mid) query(node * 2, begin, mid, l, r);
else if(l > mid) query(node * 2 + 1, mid + 1, end, l, r);
else {
query(node * 2, begin, mid, l, mid);
query(node * 2 + 1, mid + 1, end, mid + 1, r);
}
}
}
int main() {
int N, M;
while(~scanf("%d %d", &N, &M)) {
int i;
for(i = 1; i <= N; i++) {
scanf("%d", &array[i]);
}
build(1, 1, N);
int l, r;
while(M--) {
Max = 0; //一定不能忘了初值的设置
Min = 0x7fffffff;
scanf("%d %d", &l, &r);
query(1, 1, N, l, r);
printf("%d\n", Max - Min);
}
}
return 0;
}