http://acm.hdu.edu.cn/showproblem.php?pid=2888
二維RMQ,支持靜態查詢區間最值(最小或最大)
/*
hdu 2888 二維RMQ
二維RMQ,支持靜態查詢,預處理O(n*m*lgn*lgm)
下標從1開始
注意與二維線段樹的區別(支持動態更新)
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<vector>
#include<set>
#include<map>
#include<algorithm>
#include<sstream>
#define eps 1e-9
#define pi acos(-1)
#define INF 0x7fffffff
#define inf -INF
#define MM 10
#define N 1010
using namespace std;
typedef long long ll;
const int _max = 300 + 10;
int val[310][310];
int dp[310][310][9][9];
int mm[310];
int n,m,Q;
void initRMQ(int n,int m){
for(int i = 1; i <= n; ++ i)
for(int j = 1;j <= m;++j)
dp[i][j][0][0]=val[i][j];
for(int ii = 0; ii <= mm[n];++ ii)
for(int jj = 0; jj <= mm[m]; ++ jj)
if(ii+jj)
for(int i =1;i + (1<<ii)-1<=n; ++ i)
for(int j = 1;j+(1<<jj)-1<=m;++j){
if(ii)dp[i][j][ii][jj]=max(dp[i][j][ii-1][jj],dp[i+(1<<(ii-1))][j][ii-1][jj]);
else dp[i][j][ii][jj]=max(dp[i][j][ii][jj-1],dp[i][j+(1<<(jj-1))][ii][jj-1]);
}
}
//rmq查詢(x1<=x2,y1<=y2)
int rmq(int x1,int y1,int x2,int y2){
int k1= mm[x2-x1+1];
int k2 = mm[y2-y1+1];
x2=x2-(1<<k1)+1;
y2=y2-(1<<k2)+1;
return max(max(dp[x1][y1][k1][k2],dp[x1][y2][k1][k2]),max(dp[x2][y1][k1][k2],dp[x2][y2][k1][k2]));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
#endif // ONLINE_JUDGE
//mm數組初始化
mm[0]=-1;
for(int i = 1; i <= 810; ++ i)
mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
while(scanf("%d%d",&n,&m)==2){
for(int i = 1; i <= n; ++ i)
for(int j = 1;j <= m; ++ j)
scanf("%d",&val[i][j]);
int r1,c1,r2,c2,maxx;
initRMQ(n,m);
scanf("%d",&Q);
while(Q--){
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
if(r1>r2)swap(r1,r2);
if(c1>c2)swap(c1,c2);
maxx = rmq(r1,c1,r2,c2);
printf("%d ",maxx);
bool ok = (maxx==val[r1][c1])||(maxx==val[r1][c2])||(maxx==val[r2][c1])||(maxx==val[r2][c2]);
puts(ok?"yes":"no");
}
}
return 0;
}