1883: 士兵杀敌(三)
时间限制: 2 Sec 内存限制: 64 MB提交: 24 解决: 13
您该题的状态:已完成
[提交][状态][讨论版]
题目描述
南将军统率着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号士兵。
第一行是两个整数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
一道明显的线段树模板题,不会线段树请看这里:
哦,对了,这棵线段树要同时包括最大值和最小值哦,因为要求他们的差嘛
#include <stdio.h>
#define INF 0x3f3f3f3f
#define MAXN 100010
struct segmentTree{
int maxdata;
int mindata;
int start;
int end;
};
int maxTree,minTree;
int kill[ MAXN ];
segmentTree segTree[ MAXN*3 ];
int max( int aa , int bb ){
return aa>bb?aa:bb;
}
int min( int aa , int bb ){
return aa<bb?aa:bb;
}
//建立线段树
void buildTree( int pos , int start , int end ){
segTree[pos].start = start;
segTree[pos].end = end;
if( start==end ){
segTree[pos].maxdata = segTree[pos].mindata = kill[start];
}
else{
int mid = ( start+end )/2;
buildTree( 2*pos , start , mid );
buildTree( 2*pos+1 , mid+1 , end );
segTree[pos].maxdata = segTree[ 2*pos ].maxdata > segTree[ 2*pos+1 ].maxdata ? segTree[ 2*pos ].maxdata : segTree[ 2*pos+1 ].maxdata;
segTree[pos].mindata = segTree[ 2*pos ].mindata < segTree[ 2*pos+1 ].mindata ? segTree[ 2*pos ].mindata : segTree[ 2*pos+1 ].mindata;
}
}
//查询
void query( int pos , int left , int right ){
if( left<=segTree[pos].start && segTree[pos].end<=right ){
maxTree = max( maxTree , segTree[pos].maxdata );
minTree = min( minTree , segTree[pos].mindata );
}else{
int mid = ( segTree[pos].start+segTree[pos].end )/2;
if( left<=mid ){
query( pos*2 , left , right );
}
if( right>mid )
query( pos*2+1 , left , right );
// printf( "maxTree=%d\tminTree=%d\n",maxTree,minTree );
}
}
int main(){
// freopen( "input.txt","r",stdin );
int n,m;
while( ~scanf( "%d%d",&n,&m ) ){
for( int i=1 ; i<=n ; i++ ){
scanf( "%d",&kill[i] );
}
buildTree( 1,1,n );
int s,e;
while( m-- ){
scanf( "%d%d",&s,&e );
maxTree = -INF;
minTree = INF;
query( 1,s,e );
// printf( "Max=%d\n",maxTree );
// printf( "Min=%d\n",minTree );
printf( "%d\n",maxTree-minTree );
}
}
}
除了线段树呢,还有一种叫做RMQ的算法,具体也不是很懂ε=(´ο`*)))套模板好了
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define MAXN 100010
using namespace std;
int dpMax[20][MAXN];
int dpMin[20][MAXN];
void RMQ(int n) {
//j为步长
for(int j = 1; j < 17; j++ ) {
for(int i = 1; i <= n; i++ ) {
if(i + (1 << j) - 1 <= n ) {
dpMax[j][i] = max(dpMax[j - 1][i], dpMax[j - 1][i + (1 << (j - 1))]);
dpMin[j][i] = min(dpMin[j - 1][i], dpMin[j - 1][i + (1 << (j - 1))]);
}
}
}
}
int main() {
// freopen( "input.txt","r",stdin );
int n,m;
scanf( "%d%d",&n,&m );
for( int i=1 ; i<=n ; i++ ) {
scanf( "%d",&dpMax[0][i] );
dpMin[0][i] = dpMax[0][i];
}
RMQ( n );
int s,e;
while( m-- ) {
scanf( "%d%d",&s,&e );
int k = (int)( log( e-s+1.0 )/log( 2.0 ) );
int Max = max( dpMax[k][s],dpMax[k][ e-(1<<k)+1 ] );
int Min = min( dpMin[k][s],dpMin[k][ e-(1<<k)+1 ] );
printf( "%d\n",Max-Min );
}
}
如果有什么其他想法欢迎留言哦