二维的rmq 和一维的rmq 其实非常相似,我们定义 dp[r][c][i][j] 为 覆盖了 r行c列 到 r+2^i-1行 c+2^j-1列的 标记值(如最大最小)。
dp转移就很容易了:
当i为0 ,j为0 的时候就是 数组[r][c]的值, 当i= 0 ,就j不为0的时候,就和一维的rmq一样,此时即对第一行求rmq;
我们只看二维rmq的行,那么二维rmq 也变成了一维, 而且 因为求了第一行的dp相关值了,又可以按照一维的方式递推。
查询分成四块:
举个例 要查询:(3 3)( 8 9)这个子矩阵的最小值吧;因为8-3 = 5 >4 9-3=6>4
所以查询的结果为 : (3,3,)(3+4,3+4) 和 (8,3)(8,7)和 (3,8)(7,9)和 (8,8)(8,9)四个子矩形的最小值
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <cmath>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll; typedef double dl;
typedef vector<pii> vii;
typedef set<pii> sii;
#define sfint(x) scanf("%d",&x)
#define sfint2(x,y) scanf("%d%d",&x,&y)
#define sfint3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sfstr(c) scanf("%s",c)
#define pfint(x) printf("%d\n",x)
#define fr(i,s,n) for(i=s;i<n;++i)
#define _fr(i,n,s) for(i=n-1;i>=s;--i)
#define cl(a) memset(a,0,sizeof(a))
#define _has(s,x) ((s&(_ni(x)))!=0)
#define _hasL(s,x) ((s&(_niL(x)))!=0LL)
template<class T> inline T _lowbit(const int &x){ return (x^(x-1))&x; }
template<class T> inline int _bitsize(const T &x){ return (x==0)?0:(1+_bitsize(x&(x-1))); }
const dl _pi=acos(-1.0);
const dl _eps=1e-6;
const int N = 301;
int t,n;
int dp[N][N][9][9];
void in(int &a)
{
char c,f;
while(((f=getchar())<'0'||f>'9')&&f!='-');
c=(f=='-')?getchar():f;
for(a=0;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
if(f=='-')a=-a;
}
void initrmq(){
int i,j;
int m = log(double(n)) / log(2.0);
fr(i,0,m+1){
fr(j,0,m+1){
if (i==0 && j==0) continue;
for(int r = 0; r+(1<<i)-1 < n; ++r){
for(int c = 0; c+(1<<j)-1 < n; ++c){
if(i == 0) dp[r][c][i][j] = min(dp[r][c][i][j-1] , dp[r][c+(1<<(j-1))][i][j-1]);
else dp[r][c][i][j] = min(dp[r][c][i-1][j] , dp[r+(1<<(i-1))][c][i-1][j]);
}
}
}
}
}
int rmq_2d_query(int X1,int Y1,int X2,int Y2){
int x = log(double(X2 - X1 +1)) / log(2.0);
int y = log(double(Y2 - Y1 +1)) / log(2.0);
int m1 = dp[X1][Y1][x][y];
int m2 = dp[X2-(1<<x)+1][Y1][x][y];
int m3 = dp[X1][Y2-(1<<y)+1][x][y];
int m4 = dp[X2-(1<<x)+1][Y2-(1<<y)+1][x][y];
return min(min(m1,m2),min(m3,m4));
}
void inp(){
int i,j,m,X1,Y1,X2,Y2;
in(n);
fr(i , 0,n){
fr(j,0,n){
in(dp[i][j][0][0]);
}
}
initrmq();
sfint(m);
while(m--){
in(X1);in(Y1);in(X2);in(Y2);
printf("%d\n",rmq_2d_query(X1-1,Y1-1,X2-1,Y2-1));
}
}
int main(){
sfint(t);
while(t--){
inp();
}
return 0;
}