intさわだんのBlack History

刹那的レジェンドになりたい。

POJ 3264 Balanced Lineup

解法:Segment Tree(RMQ)

セグツリやるだけ

USACOの問題。

Range Minimum QueryとRange Maximum Queryを同時に処理する。

計算量O(Q lg N).

#include <cstdio>
#include <algorithm>
#include <climits>
using namespace std;
typedef pair<int,int> P;
int n,q,seg[2][121072],nn;

P query(int a,int b,int k,int l,int r){
	if(r <= a || b <= l)return P(INT_MAX,INT_MIN);

	if(a <= l && r <= b)return P(seg[0][k],seg[1][k]);
	else{
		P vl = query(a,b,k*2+1,l,(r+l)/2);
		P vr = query(a,b,k*2+2,(r+l)/2,r);
		return P(min(vl.first,vr.first),max(vl.second,vr.second));
	}
}

void update(int k,int x){
	k += nn - 1;
	seg[0][k] = x;
	seg[1][k] = x;
	while(k > 0){
		k = (k-1)/2;
		seg[0][k] = min(seg[0][k*2+1],seg[0][k*2+2]);
		seg[1][k] = max(seg[1][k*2+1],seg[1][k*2+2]);
	}
}

int main(){
	scanf("%d%d",&n,&q);
	nn = 2;
	while(nn < n)nn *= 2;
	for(int i = 0;i <= nn;i++)seg[0][i] = INT_MAX,seg[1][i] = INT_MIN;
	for(int i = 1;i <= n;i++){
		int h;
		scanf("%d",&h);
		update(i,h);
	}
	while(q--){
		int a,b;
		scanf("%d%d",&a,&b);
		b++;
		P ans = query(a,b,0,0,nn);
		printf("%d\n",ans.second-ans.first);
	}
	return 0;
}