题目描述

在麦克雷的面前出现了一个有n*m个格子的矩阵,每个格子用“.”或“#”表示,“.”表示这个格子可以放东西,“#”则表示这个格子不能放东西。现在他拿着一条1*2大小的木棒,好奇的他想知道对于一些子矩阵,有多少种放木棒的方案。

输入

第一行包含 2 个正整数 n,m。

接下来 n 行每行包含 m 个字符“.”或“#”。

第n+1行包含1个正整数q,表示询问次数。

接下来q行每行包含4个正整数r1,c1,r2,c2,分别表示询问的子矩阵的左上格子和右下格子的位置。

输出

输出共 q 行,每行包含 1 个整数,表示该询问的方案数。

样例输入

5 8

….#..#

.#……

##.#….

##..#.##

……..

4

1 1 2 3

4 1 4 1

1 2 4 5

2 5 5 8

样例输出

4

0

10

15

数据范围

30%:q<=100

100%:q<=10^5,1<=n,m<=500

样例解释

解法

把原问题转化为规定矩阵中有多少对相邻的“.”。

简单的前缀和问题。

代码

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define ll long long
#define ln(x,y) int(log(x)/log(y))
#define sqr(x) ((x)*(x))
using namespace std;
const char* fin="aP2.in";
const char* fout="aP2.out";
const int inf=0x7fffffff;
const int maxn=507;
int n,m,i,j,k,l,o,ans;
char a[maxn][maxn];
int c[maxn][maxn][4],sum[maxn][maxn][7],d[maxn][maxn][4];
bool judge(int x,int y){
return x>0 && x<=n && y>0 && y<=m && a[x][y]=='.';
}
int getsum(int sx,int sy,int tx,int ty,int kind){
if (tx<sx || ty<sy) return 0;
return sum[tx][ty][kind]-sum[sx-1][ty][kind]-sum[tx][sy-1][kind]+sum[sx-1][sy-1][kind];
}
int main(){
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) scanf("%s",a[i]+1);
for (i=1;i<=n;i++) for (j=1;j<=m;j++){
if (judge(i,j)){
if (judge(i+1,j)){
c[i][j][0]++;
c[i][j][1]++;
sum[i][j][0]++;
sum[i][j][1]++;
sum[i][j][3]++;
sum[i][j][4]++;
sum[i][j][5]++;
d[i][j][0]++;
}
if (judge(i,j+1)){
c[i][j][0]++;
c[i][j][3]++;
sum[i][j][0]++;
sum[i][j][2]++;
sum[i][j][3]++;
sum[i][j][4]++;
sum[i][j][6]++;
d[i][j][3]++;
}
if (judge(i-1,j)){
c[i][j][2]++;
c[i][j][3]++;
sum[i][j][1]++;
sum[i][j][2]++;
sum[i][j][3]++;
sum[i][j][4]++;
sum[i][j][5]++;
d[i][j][2]++;
}
if (judge(i,j-1)){
c[i][j][1]++;
c[i][j][2]++;
sum[i][j][0]++;
sum[i][j][1]++;
sum[i][j][2]++;
sum[i][j][4]++;
sum[i][j][6]++;
d[i][j][1]++;
}
}
for (k=0;k<7;k++) sum[i][j][k]+=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k];
}
scanf("%d",&i);
for (;i;i--){
scanf("%d%d%d%d",&j,&k,&l,&o);
if (j==l && k==o) ans=0;
else
if (j==l){
ans=getsum(j,k+1,j,o-1,6)+d[j][k][3]+d[j][o][1];
}else if (k==o) ans=getsum(j+1,o,l-1,o,5)+d[j][o][0]+d[l][o][2];
else {
ans=getsum(j+1,k+1,l-1,o-1,4)+c[j][k][0]+c[j][o][1]+c[l][k][3]+c[l][o][2];
ans+=getsum(j,k+1,j,o-1,0)+getsum(l,k+1,l,o-1,2);
ans+=getsum(j+1,o,l-1,o,1)+getsum(j+1,k,l-1,k,3);
}
ans/=2;
printf("%d\n",ans);
}
return 0;
}

启发

注意边界。

最新文章

  1. ABP(现代ASP.NET样板开发框架)系列之3、ABP分层架构
  2. 读取70开头的xml,gbk转成utf-8
  3. 【图像处理】第三次实验:JPEG图像压缩
  4. svg-高斯模糊+swiper伦播
  5. 直接拿来用!最火的iOS开源项目
  6. Rails--default_scope
  7. Linux下运行top命令显示的PR\NI\RES\SHR\S\%MEM TIME+都代表什么
  8. 鼠标操作[OpenCV 笔记10]
  9. JSP中的隐含对象
  10. java EE 、java SE 、java ME的区别
  11. python使用urllib2 http 下载参数的try catch
  12. mysql 开发基础系列5 字符串函数
  13. 辨析element.offsetXxxx和element.style.xxxx
  14. BZOJ4372烁烁的游戏——动态点分治+线段树(点分树套线段树)
  15. [TFS教程]TFS: Get Command
  16. MySQL架构之 主从+ProxySQL实现读写分离
  17. 阿里巴巴Java开发手册与自己开发对照笔记
  18. Centos7下关于系统用户密码规则-运维笔记
  19. session会话示例
  20. vue属性

热门文章

  1. html常用标签详解5-表格标签
  2. 给NetBeans配置javafx环境
  3. Django模型中的OneToOneField和ForeignKey有什么区别?
  4. matlab中disp函数的简单用法
  5. 禅道Mysql默认密码修改
  6. Luogu P2577 [ZJOI2005]午餐(dp)
  7. Docx 生成word文档
  8. CSS利用filter/opacity实现背景透明
  9. 关于python的列表操作(二):排序,统计
  10. 3_58 csapp 第三版的答案