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
----------------------------------------------------------------------------------------
sum[i][j] : 表示從第i個元素開始,連續2^j個元素中最值得情況;

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define N 100010
int maxsum[N][20],minsum[N][20];


void RMQ(int num)
{
	for(int j=1;j<20;j++)
	{
		for(int i=1;i<=num;i++)
		{
			if(i + (1<<j) - 1 <= num)
			{	//這裏中間元素重疊,所以第二維就可以直接用 (j-1) , 只不過前一個區間比第二個區間多覆					//蓋一個元素,
				maxsum[i][j] = max(maxsum[i][j-1],maxsum[i+(1<<(j-1))][j-1]);
				minsum[i][j] = min(minsum[i][j-1],minsum[i+(1<<(j-1))][j-1]);
			}
		}
	}
}
int main()
{
	int num,t;
	int sta,end;
	scanf("%d%d",&num,&t);
	for(int i=1;i<=num;i++)
	{
		scanf("%d",&maxsum[i][0]);
		minsum[i][0] = maxsum[i][0];
	}
	RMQ(num);
	while(t--)
	{
		scanf("%d%d",&sta,&end);
		int k = (int)(log(end - sta + 1.0) / log(2.0));
		//當詢問的區間中有偶數個元素時 [sta][k] 和 [end - (1<<k) + 1][k] 是相同的;
		int maxres = max(maxsum[sta][k],maxsum[end - (1<<k) + 1][k]);
		int minres = min(minsum[sta][k],minsum[end - (1<<k) + 1][k]);
		printf("%d\n",maxres - minres);
	}
	return 0;
}
發佈了62 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章