题目链接:没有
题目大意:
一个公司想买一块正方形的地建总部,奈何地皮到处有森林,公司无奈下决定,只好买一块正方型地,它最多含有一处森林,而且公司有的是钱,越大越好。
解题思路:
先维护一个二位前缀和数组记录1的和,行和列的范围都是1000,有T组数据,如果暴力遍历每个点,检验一个点时二分枚举边界长度,时间复杂度是O(T*(n^2) * log(n)),最大要跑2e8的数据。比赛时用scanf一直超时。比赛后试用一般的读入挂也超时,最后用了高级读入挂才AC,跑了0.4s.
代码如下:
#include<bits/stdc++.h>
using namespace std;
namespace fastIO {
#define BUF_SIZE 100000
//fread -> read
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if(p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if(pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
inline void read(int &x) {
char ch;
while(blank(ch = nc()));
if(IOerror) return;
for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
using namespace fastIO;
int sum[1005][1005], a[1005][1005];
int max(int x, int y){
return x > y ? x : y;
}
int min(int x, int y){
return x < y ? x : y;
}
int func(int x, int y, int s){
int l = 1, r = s, mid = (l+r)/2, ans = 1;
while(r >= l){
mid = (l+r)/2;
if((sum[x][y]-sum[x-mid][y]-sum[x][y-mid]+sum[x-mid][y-mid] <= 1) ) l = mid+1, ans = mid;
else r = mid-1;
}
return ans;
}
int main()
{
int t, n, m;
read(t);
while(t--){
read(n); read(m);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
read(a[i][j]);
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
}
}
int ans = 0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
int d = min(i, j);
ans = max(ans, func(i, j, d));
}
}
printf("%d\n", ans);
}
return 0;
}