分析
看到题面一个 n 3 n^3 n3 的做法显然已经跳出来了,只需要一个二维前缀和统计一下看是不是全为0就行(有洞设为1)。
但是复杂度不达标,至少要 O ( n m l o g n ) O(nmlogn) O(nmlogn),可以考虑压一维。发现他都是正方形,对于左上角相同的正方形,他是有包含关系的,所以只用找最大的一个正方形就可以了,又考虑到我们可以用前缀和 O ( 1 ) O(1) O(1) 判断是否最大,明显有二分的特点。于是二分能扩展多少个点,找到最大的正方形统计答案。
上代码
n3
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,k;
long long ans;
int s[3010][3010],x[100010],y[100010];
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x[i],&y[i]);
s[x[i]][y[i]]=1;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
s[i][j]=s[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int l=1;i+l-1<=n&&j+l-1<=m;l++)
{
if(s[i+l-1][j+l-1]-s[i+l-1][j-1]-s[i-1][j+l-1]+s[i-1][j-1]==0)
{
ans++;
}
else break;
}
}
}
printf("%lld",ans);
return 0;
}
正解:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,k;
long long ans;
int s[3010][3010],a[3010][3010],x[100010],y[100010];
bool check(int i,int j,int kk)
{
if(s[i+kk][j+kk]-s[i+kk][j-1]-s[i-1][j+kk]+s[i-1][j-1]==0)
return true;
else return false;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x[i],&y[i]);
a[x[i]][y[i]]=1;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
s[i][j]=a[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]) continue;
int l=0,r=min(n-i,m-j),mid;
while(l<r)
{
mid=(l+r)>>1;
if(check(i,j,mid))
{
l=mid+1;
}
else r=mid;
}
if(check(i,j,l)) ans+=l+1;
else ans+=l;
}
}
printf("%lld",ans);
return 0;
}