[暴力]JZOJ 5842 a

Description

给定一个n*m 的 01 矩阵,求包含[l,r]个 1 的子矩形个数。
 
 

Input

第一行,两个正整数n,m。
接下来n 行,每行一个长度为 m 的 01 串,表示给定的矩阵。接下来一行,两个自然数 l,r。
 

Output

第一行,一个整数代表答案。
 
 

Sample Input

见下发文件

Sample Output

见下发文件
 
 

Data Constraint

分析

观察到n很小,考虑n^2暴力枚举可行矩形上下界

然后我们对每一层做一个类似于队列的操作

右端点枚举,左端点有两个:一个表示l1~r1之间的数<l并且尽可能往右的,另一个表示l2~r1之间的数<=r并且尽可能往右的

然后答案就把所有l1-l2加起来就行

#pragma GCC optimize(3)
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n,m;
ll l,r,ans;
ll s[36][50011],ls[50011];

int main() {
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++) {
            char c;
            do {
                scanf("%c",&c);
            }
            while (c!='0'&&c!='1');
            s[i][j]=s[i-1][j]+c-'0';
        }
    scanf("%lld%lld",&l,&r);
    for (int i=1;i<=n;i++)
        for (int j=i;j<=n;j++) {
            ll l1=0,l2=0;
            for (int k=1;k<=m;k++) 
                ls[k]=ls[k-1]+s[j][k]-s[i-1][k];
            for (int k=1;k<=m;k++) {
                while (l1<k&&ls[k]-ls[l1]>=l) l1++;
                while (l2<k&&ls[k]-ls[l2]>r) l2++;
                ans+=l1-l2;
            }
        }
    printf("%lld",ans);
    fclose(stdin);fclose(stdout);
}
View Code

 

posted @ 2018-08-23 20:49  Vagari  阅读(207)  评论(0编辑  收藏  举报