在一个n*n的方格中找出最大的不包含障碍的正方形。(n<=1000,障碍数<=10000)
看起来好像有点难,不能随便枚举。但仔细一想,可以发现:最大的正方形中至少有一个的一边靠着障碍。于是我们只需枚举每个障碍上下左右最大的正方形是多少。
至于某一个方向最大的正方形怎么求,我们以右边的为例。我们先预处理每一列所有障碍的横坐标,排序。对于当前障碍在x行y列,j从y+1列向右推,每次用y列中最接近x的横坐标更新l,r,用l和r更新maxl和minr,正方形的边长为min(minr-maxl,j-b[i].y)。一个优化:当minr-maxl<j-b[i].y时可推出,因为再往右推的结果<=当前的minr-maxl。
注意:多余数组不要乱开,usaco training给的空间只有16MB
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define inf 2147483647
#define mp make_pair
#define pii pair<int,int>
#define pb push_back
using namespace std;
inline int read(){
int x=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
struct node{
int x,y;
}b[10001];
int a[1001][1001];
vector<int> x[1001],y[1001];
inline bool cmp(node c,node d){
return c.x<d.x;
}
inline bool cmp2(node c,node d){
return c.y<d.y;
}
int main()
{
freopen("bigbrn.in","r",stdin);
freopen("bigbrn.out","w",stdout);
int n=read(),m=read();
for(int i=1;i<=m;++i) b[i].x=read(),b[i].y=read(),a[b[i].x][b[i].y]=1;
sort(b+1,b+m+1,cmp);
for(int i=1;i<=m;++i) x[b[i].y].pb(b[i].x);
sort(b+1,b+m+1,cmp2);
for(int i=1;i<=m;++i) y[b[i].x].pb(b[i].y);
int ans=0;
for(int i=1;i<=m;++i){
int j=b[i].y+1,ml,mr;
ml=0,mr=n+1;
while(1){
if(j>n) break;
int pos,sz=x[j].size(),l,r;
if(sz==0) l=1,r=n;
else{
pos=lower_bound(x[j].begin(),x[j].end(),b[i].x)-x[j].begin();
if(pos==0) l=1,r=x[j][0]-1;
else if(pos==sz) l=x[j][pos-1]+1,r=n;
else l=x[j][pos-1]+1,r=x[j][pos]-1;
}
ml=max(ml,l);mr=min(mr,r);
ans=max(ans,min(mr-ml+1,j-b[i].y));
if(mr-ml+1<j-b[i].y) break;
++j;
}
j=b[i].y-1;ml=0,mr=n+1;
while(1){
if(j<1) break;
int pos,sz=x[j].size(),l,r;
if(sz==0) l=1,r=n;
else{
pos=lower_bound(x[j].begin(),x[j].end(),b[i].x)-x[j].begin();
if(pos==0) l=1,r=x[j][0]-1;
else if(pos==sz) l=x[j][pos-1]+1,r=n;
else l=x[j][pos-1]+1,r=x[j][pos]-1;
}
ml=max(ml,l);mr=min(mr,r);
ans=max(ans,min(mr-ml+1,b[i].y-j));
if(mr-ml+1<b[i].y-j) break;
--j;
}
j=b[i].x+1;ml=0,mr=n+1;
while(1){
if(j>n) break;
int pos,sz=y[j].size(),l,r;
if(sz==0) l=1,r=n;
else{
pos=lower_bound(y[j].begin(),y[j].end(),b[i].y)-y[j].begin();
if(pos==0) l=1,r=y[j][0]-1;
else if(pos==sz) l=y[j][pos-1]+1,r=n;
else l=y[j][pos-1]+1,r=y[j][pos]-1;
}
ml=max(ml,l);mr=min(mr,r);
ans=max(ans,min(mr-ml+1,j-b[i].x));
if(mr-ml+1<j-b[i].x) break;
++j;
}
j=b[i].x-1;ml=0,mr=n+1;
while(1){
if(j<1) break;
int pos,sz=y[j].size(),l,r;
if(sz==0) l=1,r=n;
else{
pos=lower_bound(y[j].begin(),y[j].end(),b[i].y)-y[j].begin();
if(pos==0) l=1,r=y[j][0]-1;
else if(pos==sz) l=y[j][pos-1]+1,r=n;
else l=y[j][pos-1]+1,r=y[j][pos]-1;
}
ml=max(ml,l);mr=min(mr,r);
ans=max(ans,min(mr-ml+1,b[i].x-j));
if(mr-ml+1<b[i].x-j) break;
--j;
}
}
printf("%d\n",ans);
return 0;
}