[前缀和][枚举] Jzoj P5842 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枚举矩阵的上下边界
  • 然后两个指针,x和y,记录到刚好小于l,和刚好大于r的
  • 算一波方案数就好了

代码

 1 #include <cstdio>
 2 using namespace std;
 3 char s[50010];
 4 long long n,m,i,j,p[50010],a[40][50010],sum[40][50010],q[50010],ans,k,l,r;
 5 int main()
 6 {
 7     freopen("a.in","r",stdin);
 8     freopen("a.out","w",stdout);
 9     scanf("%lld%lld",&n,&m);
10     for (int i=1;i<=n;i++)
11     {
12         scanf("%s\n",s+1);
13         for (int j=1;j<=m;j++)
14         {
15             a[i][j]=s[j]-'0';
16             sum[i][j]=sum[i-1][j]+a[i][j];
17         }
18     }
19     scanf("%lld%lld\n",&l,&r);
20     for (int i=1;i<=n;i++)
21         for (int j=i;j<=n;j++)
22         {
23             long long x=0,y=0;
24             for (int k=1;k<=m;k++)
25             {
26                 p[k]=sum[j][k]-sum[i-1][k];
27                 q[k]=q[k-1]+p[k];
28             }
29             for (int k=1;k<=m;k++)
30             {
31                 while (q[k]-q[x]>=l&&x<k) x++;
32                 while (q[k]-q[y]>r&&y<k) y++;
33                 ans+=x-y;
34             } 
35         }
36     printf("%lld\n",ans);
37     return 0;
38 } 

 

posted @ 2018-08-23 21:28  BEYang_Z  阅读(200)  评论(0编辑  收藏  举报