题意:给定一个二维矩阵,然后有Q个询问,每个询问给出两个坐标,求以这两个坐标为左上角和右下角的矩阵内的最大值,并判断这个值是否是矩阵四个角的值。
分析:二维RMQ裸题。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 300+5;
int dmax[N][N][9][9];
int n,m,q;
void init()
{
for(int i=0;(1<<i)<=n;i++)
for(int j=0;(1<<j)<=m;j++)
{
if(i==0&&j==0) continue;
for(int x=1;x+(1<<i)-1<=n;x++)
for(int y=1;y+(1<<j)-1<=m;y++)
{
if(j) dmax[x][y][i][j]=max(dmax[x][y][i][j-1],dmax[x][y+(1<<(j-1))][i][j-1]);
else dmax[x][y][i][j]=max(dmax[x][y][i-1][j],dmax[x+(1<<(i-1))][y][i-1][j]);
}
}
}
int query(int x0,int y0,int x1,int y1)
{
if(x0==x1&&y1==y0) return dmax[x0][y0][0][0];
int cntx=0,cnty=0;
while(x0+(1<<(cntx+1))-1<=x1) cntx++;
while(y0+(1<<(cnty+1))-1<=y1) cnty++;
int m1=dmax[x0][y0][cntx][cnty];
int m2=dmax[x1-(1<<cntx)+1][y0][cntx][cnty];
int m3=dmax[x0][y1-(1<<cnty)+1][cntx][cnty];
int m4=dmax[x1-(1<<cntx)+1][y1-(1<<cnty)+1][cntx][cnty];
int Max=max(max(m1,m2),max(m3,m4));
return Max;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&dmax[i][j][0][0]);
init();
scanf("%d",&q);
while(q--)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int ans=query(x1,y1,x2,y2);
printf("%d ",ans);
int flag=0;
if(dmax[x1][y1][0][0]==ans) flag=1;
if(dmax[x1][y2][0][0]==ans) flag=1;
if(dmax[x2][y1][0][0]==ans) flag=1;
if(dmax[x2][y2][0][0]==ans) flag=1;
if(flag) puts("yes");
else puts("no");
}
}
//system("pause");
}