CF131F
先枚举矩形左上角坐标 \((x_1,y_1)\),以及右下角横坐标 \(x_2\),则可得右下角纵坐标 \(y_2\in [y_1,m]\)。显然,随着 \(y_2\) 的增大,矩形内符合图形的数量只增不减,故可以二分出第一个位置使得该数量恰好为 \(k\)。计算矩阵内符合图形的数量使用二位前缀和。时间复杂度 \(O(n^2m\log m)\)。
#include<iostream>
#include<cstdio>
using namespace std;
string t;
int n,m,k,a[510][510],s[510][510];
long long ans;
int sum(int x1,int y1,int x2,int y2){
if(x1>x2||y1>y2)return 0;
return s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
cin>>t;
for(int j=1;j<=m;j++)
a[i][j]=t[j-1]-'0';
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
if(a[i][j]&&a[i][j-1]&&a[i][j+1]&&a[i-1][j]&&a[i+1][j])
s[i][j]++;
}
}
for(int x1=1;x1<=n;x1++)
for(int y1=1;y1<=m;y1++)
for(int x2=x1;x2<=n;x2++){
int l=y1,r=m,mid,y2=m;
if(sum(x1+1,y1+1,x2-1,y2-1)<k)continue;
while(l<=r){
mid=(l+r)/2;
if(sum(x1+1,y1+1,x2-1,mid-1)>=k)y2=mid,r=mid-1;
else l=mid+1;
}
// cout<<x1+1<<' '<<y1+1<<' '<<x2-1<<' '<<y2-1<<' '<<sum(x1+1,y1+1,x2-1,y2-1)<<endl;
ans+=m-y2+1;
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号