题目链接:传送门
题目大意;给定一个n * m的矩阵,再给定q个询问,每次询问(r1,c1)为左上角,(r2,c2)为右下角的子矩形的最大值,并且判断该最大值是否出现在了这个子矩阵的4个顶角上?
思路:二维RMQ模板即可。
注意:此题有两个点需要注意,他会卡内存,所以你要考虑数组的大小,不能开太大。
其次他会卡输入时间,这就很变态了,不能用cin会超时,要改用scanf。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define maxn 310
int val[maxn][maxn];
int m[maxn];
int dpmax[maxn][maxn][9][9];
//int dpmin[maxn][maxn][10][10];
int n,nn;
void RMQ_init()
{
//int nlog=(int)(log(double(len))/log(2.0));
for(int i=1;i<=n;i++)
for(int j=1;j<=nn;j++)
//dpmax[i][j][0][0]=dpmin[i][j][0][0]=val[i][j];
dpmax[i][j][0][0]=val[i][j];
for(int ii=0;ii<=m[n];ii++)
{
for(int jj=0;jj<=m[nn];jj++)
{
if(ii+jj)
{
for(int i=1;i+(1<<ii)-1<=n;i++)
{
for(int j=1;j+(1<<jj)-1<=nn;j++)
{
if(ii)
{
// dpmin[i][j][ii][jj]=min(dpmin[i][j][ii-1][jj],dpmin[i+(1<<(ii-1))][j][ii-1][jj]);
dpmax[i][j][ii][jj]=max(dpmax[i][j][ii-1][jj],dpmax[i+(1<<(ii-1))][j][ii-1][jj]);
}
else
{
// dpmin[i][j][ii][jj]=min(dpmin[i][j][ii][jj-1],dpmin[i][j+(1<<(jj-1))][ii][jj-1]);
dpmax[i][j][ii][jj]=max(dpmax[i][j][ii][jj-1],dpmax[i][j+(1<<(jj-1))][ii][jj-1]);
}
}
}
}
}
}
}
int RMQ_Query(int x1,int y1,int x2,int y2)
{
int k1=m[x2-x1+1];
int k2=m[y2-y1+1];
x2=x2-(1<<k1)+1;
y2=y2-(1<<k2)+1;
int ma=max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
// int mi=min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
return ma;
}
int main()
{
m[0]=-1;
for(int i=1;i<305;i++)
{
m[i]=((i&(i-1))==0)?m[i-1]+1:m[i-1];
}
int b,k;
while(~scanf("%d%d",&n,&nn))
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=nn;j++)
{
cin>>val[i][j];
}
}
RMQ_init();
scanf("%d",&k);
while(k--)
{
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1>x2)swap(x1,x2);
if(y1>y2)swap(y1,y2);
int tmp=RMQ_Query(x1,y1,x2,y2);
printf("%d ",tmp);
if(tmp == val[x1][y1] || tmp == val[x1][y2] || tmp == val[x2][y1] || tmp == val[x2][y2])
printf("yes\n");
else printf("no\n");
}
}
return 0;
}