Given an n*n matrix A, whose entries Ai,j are integer numbers ( 1 <= i <= n, 1 <= j <= n ). An operation FIND the minimun number in a given ssub-matrix.
Input
The first line of the input contains a single integer T , the number of test cases.
For each test case, the first line contains one integer n (1 <= n <= 300), which is the sizes of the matrix, respectively. The next n lines with n integers each gives the elements of the matrix.
The next line contains a single integer N (1 <= N <= 1,000,000), the number of queries. The next N lines give one query on each line, with four integers r1, c1, r2, c2 (1 <= r1 <= r2 <= n, 1 <= c1 <= c2 <= n), which are the indices of the upper-left corner and lower-right corner of the sub-matrix in question.
Output
For each test case, print N lines with one number on each line, the required minimum integer in the sub-matrix.
Sample Input
1
2
2 -1
2 3
2
1 1 2 2
1 1 2 1
Sample Output
-1
2
题意: 给一个n*n的矩阵,每次查找(L1,R1)->(L2,R2)子矩阵的最小值。
分析: 树套树,想法很简单,每次找(L1,L2) 区间并进入子树找(R1,R2)区间的最小值,
只是要注意在建树回溯的过程中 二维区间下的 pushup不再是简单的由下往上的一个区间的合并,而是整棵树所有对应一维区间的合 并,我的程序中是一个"update"。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int mn[300<<2][300<<2];
int n;
int ans;
void pushup(int k, int rt)
{
mn[k][rt] = min(mn[k][rt<<1],mn[k][rt<<1|1]);
}
void update(int k, int l, int r, int rt)
{
if(l==r)
{
mn[k][rt] = min(mn[k<<1][rt],mn[k<<1|1][rt]);
return;
}
int m = (l+r)>>1;
update(k,l,m,rt<<1);
update(k,m+1,r,rt<<1|1);
pushup(k,rt);
}
void build1(int k, int l, int r, int rt)
{
if(l==r)
{
scanf("%d",&mn[k][rt]);
return;
}
int m = (l+r)>>1;
build1(k,l,m,rt<<1);
build1(k,m+1,r,rt<<1|1);
pushup(k,rt);
}
void build2(int l, int r, int rt)
{
if(l==r)
{
build1(rt,1,n,1);
return;
}
int m = (l+r)>>1;
build2(l,m,rt<<1);
build2(m+1,r,rt<<1|1);
update(rt,1,n,1);
}
void query1(int k,int L, int R, int l, int r, int rt)
{
if(L<=l && R>=r)
{
ans = min(ans,mn[k][rt]);
return;
}
int m = (l+r)>>1;
if(L<=m) query1(k,L,R,l,m,rt<<1);
if(R>m ) query1(k,L,R,m+1,r,rt<<1|1);
}
void query2(int L1,int R1, int L2, int R2, int l, int r, int rt)
{
if(L1<=l && R1>=r)
{
query1(rt,L2,R2,1,n,1);
return;
}
int m = (l+r)>>1;
if(L1<=m) query2(L1,R1,L2,R2,l,m,rt<<1);
if(R1>m) query2(L1,R1,L2,R2,m+1,r,rt<<1|1);
}
int main()
{
int i,j,k,m,T;
int L1,L2,R1,R2;
cin>>T;
while(T--)
{
scanf("%d",&n);
build2(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d%d",&L1,&R1,&L2,&R2);
ans = 1100000000;
query2(L1,L2,R1,R2,1,n,1);
printf("%d\n",ans);
}
}
}