cf 611 A||codeforces goodbye 2015 C. New Year and Domino

http://codeforces.com/contest/611/problem/C 题意:给出一个n*m的地图,.表示可以空,#表示墙。一个东西需要占两个相邻的格子,问给定一个矩形,放一个东西的方案数。 思路:q很大。。应该是先预处理出来直接调用答案。。。计数问题累加性。。应该是前缀和之类。。需要做的就是怎么标记。。我的做法是竖着放和横着放的个数分开来存。从左往右从上往下,每次标记到后一个点。然后二维的前缀和。然后每次询问的时候,去掉最上边和最左边两条边界上对应的多加的点。

1#include <cstdio>
2#include <cstring>
3#include <iostream>
4#include <algorithm>
5#include <vector>
6#include <queue>
7#include <set>
8#include <map>
9#include <string>
using namespace std;
1const int N=5E2+7;
2char maze[N][N];
3int n,m;
4int q;
5int a[N][N],b[N][N];
6int sum[N][N];
7int sum2[N][N];
 1int main()
 2{
 3	cin>>n>>m;
 4	memset(a,0,sizeof(a));
 5	memset(b,0,sizeof(b));
 6	for ( int i = 0  ; i< n ;i++ ) scanf("%s",maze[i]);
 7	for ( int i = 1 ;  i < n ; i++)
 8	{
 9	    for (int  j =  0 ; j< m ;j++)
10	    {
11		if (maze[i][j]=='.'&&maze[i-1][j]=='.')
12		    a[i+1][j+1]++;
13	    }
14	}
 1	for ( int i = 0 ; i < n ; i++)
 2	{
 3	    for ( int j = 1 ;  j < m ; j++)
 4	    {
 5		if (maze[i][j]=='.'&&maze[i][j-1]=='.')
 6		    b[i+1][j+1]++;
 7	    }
 8	}
 9	sum[0][0] = 0;
10	sum2[0][0] =  0;
11	for ( int i = 1 ; i <= n ; i++)
12	{
13	    for ( int j = 1 ;  j<= m ; j++)
14	    {
15		sum[i][j] =sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
16		sum2[i][j] = sum2[i-1][j]+sum2[i][j-1]-sum2[i-1][j-1] + b[i][j];
17	    }
18	}
19	cin>>q;
 1	while (q--)
 2	{
 3	    int n1,n2,m1,m2;
 4	    scanf("%d %d %d %d",&n1,&m1,&n2,&m2);
 5	    int ans = 0 ;
 6	    ans+=sum[n2][m2]-sum[n1-1][m2]-sum[n2][m1-1]+sum[n1-1][m1-1];
 7	    ans+=sum2[n2][m2]-sum2[n1-1][m2]-sum2[n2][m1-1]+sum2[n1-1][m1-1];
 8	    for ( int j = m1 ; j <= m2 ;j++)
 9	    {
10		if (a[n1][j]==1) ans--;
11	    }
12	    for ( int i = n1 ; i <= n2 ; i++)
13	    {
14		if (b[i][m1]==1) ans--;
15	    }
	    printf("%d\n",ans);
	}

    return 0;
}