Description
Analysis
显然的,可以
O(n⋅m)
求出所有以(i,j)为右下角的 最大的 正方形的 边长
DP方程类似于Usaco5.3.4 Big Barn
求出所有F后,由于正方形可能超出询问中的边界
考虑二分答案Mid
因为,有些以 [i,j] 为右下角的正方形超出了范围,故二分Mid限制之
之后,问题转化为 记Mx为 左上角为(x1+mid-1,y1+mid-1) 右下角为(x2,y2)的矩阵中,F的最大值
于是,显然的,若
Mx>=Mid
说明Mx可行 二分上调,反之不行。
如图[图来自 冼]
注意常数优化!
2016.10.12 晚 更新
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int n,m,Twi[11],f[N][N],RMQ[11][11][N][N];
bool map[N][N];
char ch;
int read()
{
int t=0,p=1;
for(ch=getchar();ch<'0' || ch>'9';ch=getchar())
if(ch=='-') p=-1;
for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0';
return t*p;
}
int query(int x1,int y1,int x2,int y2)
{
if(x1 > x2 || y1 > y2) return 0;
int l1 = log2(x2 - x1 + 1), l2 = log2(y2 - y1 + 1);
int Rt = max(RMQ[l1][l2][x2][y2], RMQ[l1][l2][x2][y1 + Twi[l2] - 1]);
Rt = max(Rt,max(RMQ[l1][l2][x1 + Twi[l1] - 1][y2],RMQ[l1][l2][x1 + Twi[l1] - 1][y1 + Twi[l2] - 1]));
return Rt;
}
int main()
{
freopen("D:/LiuYuanHao/4817.in","r",stdin);
//freopen("square.in","r",stdin);freopen("square.out","w",stdout);
Twi[0] = 1;
for (int i = 1;i <= 10;i ++) Twi[i] = Twi[i - 1] << 1;
n = read(),m = read();
for (int i = 1;i <= n;i ++)
{
for (int j = 1;j <= m;j ++)
{
map[i][j]=read();
if(map[i][j]) f[i][j]=min(min(f[i-1][j],f[i][j-1]),f[i-1][j-1])+1;
RMQ[0][0][i][j]=f[i][j];
}
}
for (int k = 1;k <= log2(n);k ++)
{
for (int i = 1;i <= n;i ++)
{
for (int j = 1;j <= m;j ++)
{
RMQ[0][k][i][j]=max(RMQ[0][k-1][i][j],RMQ[0][k-1][i][j-Twi[k-1]]);
RMQ[k][0][i][j]=max(RMQ[k-1][0][i][j],RMQ[k-1][0][i-Twi[k-1]][j]);
}
}
}
for (int k = 1;k <= log2(n);k ++)
for (int l = 1;l <= log2(m);l ++)
for (int i = Twi[k];i <= n;i ++)
for (int j = Twi[l];j <= m;j ++)
RMQ[k][l][i][j]=max(RMQ[k][l-1][i][j],RMQ[k][l-1][i][j-Twi[l-1]]);
for (int _ = read();_ --;)
{
int x1,y1,x2,y2;
x1 = read(),y1 = read(),x2 = read(),y2 = read();
int l = 0,r = min(y2 - y1 + 1,x2 - x1 + 1);
while (l + 1 < r)
{
int mid = (l + r) >> 1;
if (query(x1 + mid - 1, y1 + mid - 1, x2, y2) >= mid)
l = mid;
else r = mid - 1;
}
while (query(x1 + l, y1 + l, x2, y2) > l) l ++;
printf("%d\n",l);
}
}