AOJ 1068 School of Killifish

問題

h x wの長方形の土地がある。
それぞれのマスの危険度grid[i][j]が与えられる。
このとき、次のようなクエリq個に答えよ。


(r1[i], c1[i]), (r2[i], c2[i])を頂点とするような長方形の中で、
最も危険度が低いマスの危険度の値を答える。

制約条件

h * w≦10^6
q≦10^4

方針

二次元のSegment Treeを書けばいい。
そのまま拡張して書くだけ、なんだけど添え字が多くなって面倒。


AOJのMLEの基準が謎。
二次元配列をvector<vector<int> >で取ったらMLEで、
一次元配列に展開してmallocで取ったら使用メモリ量Lowで通った。

ソースコード

int h, w, q, H, W, W_;
int y1, x1, y2, x2, *g, sz;
 
int rec(int Y1, int X1, int Y2, int X2, int y, int x){
	if(y2 <= Y1 || y1 >= Y2 || x2 <= X1 || x1 >= X2) return inf;
	if(y1 <= Y1 && Y2 <= y2 && x1 <= X1 && X2 <= x2) return g[y*W_ + x];
	int res = inf;
	 
	if(Y1+1 == Y2)
		res = min(res,
			min(
				rec(Y1, X1, Y2, (X1+X2) / 2, y, x*2 + 1),
				rec(Y1, (X1+X2) / 2, Y2, X2, y, x*2 + 2)
			));
	else if(X1+1 == X2)
		res = min(res,
			min(
				rec(Y1, X1, (Y1+Y2) / 2, X2, y*2 + 1, x),
				rec((Y1+Y2) / 2, X1, Y2, X2, y*2 + 2, x)
			));
	else{
		res = min(res,
			min(
				rec(Y1, X1, (Y1+Y2) / 2, (X1+X2) / 2, y*2 + 1, x*2 + 1),
				rec((Y1+Y2) / 2, X1, Y2, (X1+X2) / 2, y*2 + 2, x*2 + 1)
			));
		res = min(res,
			min(
				rec(Y1, (X1+X2) / 2, (Y1+Y2) / 2, X2, y*2 + 1, x*2 + 2),
				rec((Y1+Y2) / 2, (X1+X2) / 2, Y2, X2, y*2 + 2, x*2 + 2)
			));
	}
	return res;
}
 
int main(){
	g = NULL;
	while(scanf("%d%d%d", &h ,&w, &q), w){
		for(H = 1; H < h; H *= 2);
		for(W = 1; W < w; W *= 2);
		W_ = 2*W - 1;
		if(sz < (2*H-1) * (2*W-1)){
			sz = (2*H-1) * (2*W-1);
			g = (int*) realloc(g, sizeof(int) * sz);
		}
		rep(i, (2*H-1) * (2*W-1)) g[i] = inf;
		rep(i,h) rep(j,w)
			scanf("%d", g + (i+H-1) * W_ + j+W-1);
		for(int i = 2*H - 2; i >= 0; i--){
			for(int j = 2*W - 2; j >= 0; j--){
				if(i < H-1 && j < W-1)
					g[i*W_ + j] = min(min(g[(i*2+1) * W_ + j*2 + 1], g[(i*2+2) * W_ + j*2+2]),
						min(g[(i*2+2) * W_ + j*2+1], g[(i*2+1) * W_ + j*2+2]));
				if(i < H-1) 
					g[i*W_ + j] = min(g[i*W_ + j], min(g[(i*2+1) * W_ + j], g[(i*2+2) * W_ + j]));
				if(j < W-1)
					g[i*W_ + j] = min(g[i*W_ + j], min(g[i*W_ + j*2+1], g[i*W_ + j*2+2]));
			}
		}
		rep(i, q){
			scanf("%d%d%d%d", &y1, &x1, &y2, &x2);
			y2++; x2++;
			printf("%d\n", rec(0, 0, H, W, 0, 0));
		}
	}
	if(g) free(g);
	return 0;
}