类型:二维线段树
来源: ZOJ Monthly, June 2007
题目:给定一个矩阵,查询该矩阵某个区间的最小值
思路:输入矩阵,建立二维线段树【建树过程中记录各区间的最小值】,查询结果
// zoj 2859 Matrix Searching
// sf sf ac 2450ms 6568kb
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define FOR(i,a,b) for(i = (a); i < (b); ++i)
#define FORE(i,a,b) for(i = (a); i <= (b); ++i)
#define FORD(i,a,b) for(i = (a); i > (b); --i)
#define FORDE(i,a,b) for(i = (a); i >= (b); --i)
#define CLR(a,b) memset(a,b,sizeof(a))
const int MAXN = 310;
const int INF = 0x7f7f7f7f;
int n;
int a[MAXN][MAXN];
int tree[MAXN << 2][MAXN << 2];
void sub_build(int proot, int root, int l0, int r0, int l, int r) {
if(l == r) {
if(l0 == r0)
tree[proot][root] = a[l0][l];
else
tree[proot][root] = min(tree[proot << 1][root], tree[proot << 1 | 1][root]);
return ;
}
int mid = (l + r) >> 1;
sub_build(proot, root << 1, l0, r0, l, mid);
sub_build(proot, root << 1 | 1, l0, r0, mid + 1, r);
//!!!
tree[proot][root] = min(tree[proot][root << 1], tree[proot][root << 1 | 1]);
}
void build(int root, int l, int r) {
if(l == r) {
sub_build(root, 1, l, r, 1, n);
return ;
}
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
sub_build(root, 1, l, r, 1, n);
}
int sub_query(int proot, int root, int l, int r, int y1, int y2) {
if(l == y1 && r == y2)
return tree[proot][root];
int mid = (l + r) >> 1;
if(mid >= y2)
return sub_query(proot, root << 1, l, mid, y1, y2);
else if(mid < y1)
return sub_query(proot, root << 1 | 1, mid + 1, r, y1, y2);
else
return min(sub_query(proot, root << 1, l, mid, y1, mid), sub_query(proot, root << 1 | 1, mid + 1, r, mid + 1, y2));
}
int query(int root, int l, int r, int x1, int x2, int y1, int y2) {
if(l == x1 && r == x2)
return sub_query(root, 1, 1, n, y1, y2);
int mid = (l + r) >> 1;
if(mid >= x2)
return query(root << 1, l, mid, x1, x2, y1, y2);
else if(mid < x1)
return query(root << 1 | 1, mid + 1, r, x1, x2, y1, y2);
else
return min(query(root << 1, l, mid, x1, mid, y1, y2), query(root << 1 | 1, mid + 1, r, mid + 1, x2, y1, y2));
}
int main() {
int T, C, r1, r2, c1, c2, i, j;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
FORE(i, 1, n) FORE(j, 1, n)
scanf("%d", &a[i][j]);
build(1, 1, n);
scanf("%d", &C);
FOR(i, 0, C) {
scanf("%d %d %d %d", &r1, &c1, &r2, &c2);
printf("%d\n", query(1, 1, n, r1, r2, c1, c2));
}
}
return 0;
}