Codeforces Round #219 (Div. 2) D题

D. Counting Rectangles is Fun
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

There is an n × m rectangular grid, each cell of the grid contains a single integer: zero or one. Let's call the cell on the i-th row and the j-th column as (i, j).

Let's define a "rectangle" as four integers a, b, c, d (1 ≤ a ≤ c ≤ n; 1 ≤ b ≤ d ≤ m). Rectangle denotes a set of cells of the grid {(x, y) :  a ≤ x ≤ c, b ≤ y ≤ d}. Let's define a "good rectangle" as a rectangle that includes only the cells with zeros.

You should answer the following q queries: calculate the number of good rectangles all of which cells are in the given rectangle.

Input

There are three integers in the first line: nm and q (1 ≤ n, m ≤ 40, 1 ≤ q ≤ 3·105). Each of the next n lines contains m characters — the grid. Consider grid rows are numbered from top to bottom, and grid columns are numbered from left to right. Both columns and rows are numbered starting from 1.

Each of the next q lines contains a query — four integers that describe the current rectangle, abcd (1 ≤ a ≤ c ≤ n; 1 ≤ b ≤ d ≤ m).

Output

For each query output an answer — a single integer in a separate line.

Sample test(s)
input
5 5 5
00101
00000
00001
01000
00001
1 2 2 4
4 5 4 5
1 2 5 2
2 2 4 5
4 2 5 3
output
10
1
7
34
5
input
4 7 5
0000100
0000010
0011000
0000000
1 7 2 7
3 1 3 1
2 3 4 5
1 2 2 7
2 2 4 7
output
3
1
16
27
52

 //题意:给出一个矩阵每次输入给出查询的范围a,b,c,d求出范围内由0做成的的矩形的个数

sol: 矩阵上的dp,可以这么想例如是1维的给出:000111000,dp方程很容易dp[i] = dp[i-1]+sum[i]; 为什么,加上前缀和嫩? 可以验证一下每次向后移动一位则增加的矩阵数目为当前位和前面每一位组成的矩形加上当前的矩形,正好是前缀和(fuck-理解了好久),转换到二维上就容易了,同样是矩阵从小到大枚举

 1 #include <cstdio>
 2 #include <vector>
 3 #include <set>
 4 #include <algorithm>
 5 using namespace std;
 6 //using PII = pair<int,int>;
 7 //using LL = long long;
 8 const int INF = 1000000007;
 9 
10 int a[45][45],cnt[45][45][45][45];
11 int s[45][45],sum[45][45][45][45];
12 
13 int main(){
14     int n,m,cs;
15     scanf("%d%d%d",&n,&m,&cs);
16     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
17         scanf("%1d",&a[i][j]);
18         s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
19       //  printf("%d %d %d ",i,j,s[i][j]);
20     }
21     for(int i=n;i>=1;i--) for(int j=m;j>=1;j--)
22     for(int r=i;r<=n;r++) for(int c=j;c<=m;c++){
23         int dot=s[r][c]-s[r][j-1]-s[i-1][c]+s[i-1][j-1];
24      //   printf("%d %d %d %d %d ",i,j,r,c,dot);
25         cnt[i][j][r][c]=cnt[i][j][r-1][c]+cnt[i][j][r][c-1]-cnt[i][j][r-1][c-1]+!dot;
26     }
27     for(int i=n;i>=1;i--) for(int j=m;j>=1;j--)
28     for(int r=i;r<=n;r++) for(int c=j;c<=m;c++)
29         sum[i][j][r][c]=sum[i+1][j][r][c]+sum[i][j+1][r][c]-sum[i+1][j+1][r][c]+cnt[i][j][r][c];
30     while(cs--)
31     {
32         int a,b,c,d;
33         scanf("%d%d%d%d",&a,&b,&c,&d);
34         printf("%d ",sum[a][b][c][d]);
35     }

36 } 

原文地址:https://www.cnblogs.com/acvc/p/3581251.html