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;
}
posted @ 2025-09-12 08:15  FormulaOne  阅读(9)  评论(0)    收藏  举报