Codeforces 611C New Year and Domino(二维前缀和)

题目大概说给一个n*m个格子,格子'.'表示可以放东西,多次询问矩形区域(x1,y1)-(x2,y2)有几种放一张1*2的骨牌的方案数。

分别考虑横着竖着放,预处理出二维的前缀和,即sum[x][y]表示(1,1)-(x,y)的横着或者竖着放的方案数,然后对于每一个询问就拆成几个前缀和容斥一下。。

细节要注意。。骨牌是1*2的。。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 char map[555][555];
 5 int hsum[555][555],vsum[555][555];
 6 int main(){
 7     int n,m;
 8     scanf("%d%d",&n,&m);
 9     for(int i=1; i<=n; ++i){
10         for(int j=1; j<=m; ++j){
11             scanf(" %c",&map[i][j]);
12         }
13     }
14 
15     for(int i=1; i<=n; ++i){
16         for(int j=2; j<=m; ++j){
17             int t=(map[i][j]=='.' && map[i][j-1]=='.');
18             if(i==0){
19                 hsum[i][j]=hsum[i][j-1]+t;
20             }else{
21                 hsum[i][j]=hsum[i][j-1]+hsum[i-1][j]-hsum[i-1][j-1]+t;
22             }
23         }
24     }
25     for(int i=2; i<=n; ++i){
26         for(int j=1; j<=m; ++j){
27             int t=(map[i][j]=='.' && map[i-1][j]=='.');
28             if(j==0){
29                 vsum[i][j]=vsum[i-1][j]+t;
30             }else{
31                 vsum[i][j]=vsum[i][j-1]+vsum[i-1][j]-vsum[i-1][j-1]+t;
32             }
33         }
34     }
35 
36     int q,x1,y1,x2,y2;
37     scanf("%d",&q);
38     while(q--){
39         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
40         int res=hsum[x2][y2]-hsum[x2][y1]-hsum[x1-1][y2]+hsum[x1-1][y1];
41         res+=vsum[x2][y2]-vsum[x2][y1-1]-vsum[x1][y2]+vsum[x1][y1-1];
42         printf("%d\n",res);
43     }
44     return 0;
45 }

 

posted @ 2016-07-24 10:00  WABoss  阅读(576)  评论(0编辑  收藏  举报