zoj 2859 Matrix Searching

来源:互联网 发布:南阳理工软件 编辑:程序博客网 时间:2024/05/18 01:56

类型:二维线段树

来源: 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;}