Check Corners HDU - 2888
原题链接
考察:RMQ
思路:
二维模板题
Code
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 310,M = 10;
int m, n,w[N][N],Q,f[N][M][N][M];
void init()
{
for (int x = 0; x < M;x++)
for (int y = 0; y < M;y++)
for (int i = 1; i + (1 << x) - 1 <= m;i++)
for (int j = 1; j + (1 << y) - 1 <= n;j++)
{
f[i][x][j][y] = 0;
if(!x&&!y)
f[i][x][j][y] = w[i][j];
else if(!x)
f[i][x][j][y] = max(f[i][x][j][y - 1], f[i][x][j + (1 << y - 1)][y - 1]);
else if(!y)
f[i][x][j][y] = max(f[i][x - 1][j][y], f[i + (1 << x - 1)][x-1][j][y]);
else
f[i][x][j][y] = max(f[i][x - 1][j][y - 1], f[i + (1 << x - 1)][x - 1][j][y - 1]),
f[i][x][j][y] = max(f[i][x][j][y], f[i][x - 1][j + (1 << y - 1)][y - 1]),
f[i][x][j][y] = max(f[i][x][j][y], f[i + (1 << x - 1)][x - 1][j + (1 << y - 1)][y - 1]);
}
}
bool check(int a,int b,int c,int d,int res)
{
if(w[a][b]==res)
return 1;
if(w[a][d]==res)
return 1;
if(w[c][b]==res)
return 1;
if(w[c][d]==res)
return 1;
return 0;
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
for (int i = 1; i <= m;i++)
for (int j = 1; j <= n;j++)
scanf("%d", &w[i][j]);
init();
scanf("%d", &Q);
while(Q--)
{
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
int ak = log(c - a + 1) / log(2), bk = log(d - b + 1) / log(2);
int ans = max(f[a][ak][b][bk], f[a][ak][d - (1 << bk) + 1][bk]);
ans = max(f[c - (1 << ak) + 1][ak][b][bk], ans);
ans = max(f[c - (1 << ak) + 1][ak][d - (1 << bk) + 1][bk],ans);
printf("%d ", ans);
if(check(a,b,c,d,ans))
printf("yes\n");
else
printf("no\n");
}
}
return 0;
}