1. 程式人生 > >nyoj 119 士兵殺敵(三)

nyoj 119 士兵殺敵(三)

描述

南將軍統率著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就能解決

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define max_n 100030
int nmax[max_n][20];
int nmin[max_n][20];
int n;
void rmq()
{
	int i, j;
	for (j = 1; (1 << j) <= n; j++)
		for (i = 0; i + (1 << j) - 1 < n; i++)
		{
			nmax[i][j] = max(nmax[i][j - 1], nmax[i + (1 << (j - 1))][j - 1]);
			nmin[i][j] = min(nmin[i][j - 1], nmin[i + (1 << (j - 1))][j - 1]);
		}
}
int search(int a, int b)
{
	int j = (int)log2(b - a + 1.0);
	return max(nmax[a][j], nmax[b - (1 << j) + 1][j]) - min(nmin[a][j], nmin[b - (1 << j) + 1][j]);
}
int main()
{
	int m;
	int i;
	scanf("%d%d",&n,&m);
	for (i = 0; i < n; i++)
	{
		scanf("%d",&nmax[i][0]);
		nmin[i][0] = nmax[i][0];
	}
	rmq();
	while (m--)
	{
		int a, b;
		scanf("%d%d",&a,&b);
		printf("%d\n",search(a - 1, b - 1));
	}
}