牛客寒假算法基础集训营6 E 海啸

链接:https://ac.nowcoder.com/acm/contest/332/E
来源:牛客网

有一个沿海地区,可以看作有n行m列的城市,第i行第j列的城市海拔为h[i][j]。
由于沿海,所以这个地区经常会发生海啸。
海啸发生时,部分城市会被淹没,具体来说,海水高度会达到d,因此海拔低于d的城市都会被淹没。
现在有q次询问,每次问你一个矩形区域中,有多少城市不会被淹没。

输入描述:

第一行三个整数n,m,d,具体含义见题目描述。
接下来n行,每行m个整数,其中第i行第j列的整数为h[i][j],具体含义见题目描述。
第n+2行一个整数q,表示询问数。
接下来q行,每行四个整数a,b,x,y,
表示询问从第a行第b列到第x行第y列的矩形地区中,有多少地区不会被淹没。
即有多少个i,j,满足 aix,bjya≤i≤x,b≤j≤y ,且 h[i][j]dh[i][j]≥d 。

输出描述:

共q行,第i行一个整数,表示第i个询问的答案。
示例1

输入

复制
3 3 3
1 2 3
2 1 5
4 3 2
2
1 2 2 3
2 1 3 3

输出

复制
2
3


记得之前见过类似的 以为是 二维线段树
看了题解 是前缀和。。

首先 明白如何求 (a,b) (x,y) 矩阵的和
容斥定理

可以看出 求 (a,b)~(x,y)的和 = sum(x,y)-sum(x,b-1)-sum(a-1,y)+sum(a-1,b-1)

其中 sum(s,t) 为 (1,1)~(s,t)的和
也即 结果 = 总矩阵 - 绿矩阵 - 黄矩阵 + 红色区域


那么如何利用 前缀和 求 sum呢

具体见代码 ,结合二维数阵 理解

 1 #include<stdio.h>
 2 const int maxn=2000010;//2倍大小
 3 int n,m,d;
 4 int h[maxn],sum[maxn];
 5 
 6 int main() {
 7     scanf("%d%d%d",&n,&m,&d);
 8     int t;
 9     for(int i=1;i<=n;i++) 
10         for(int j=1;j<=m;j++) {
11             scanf("%d",&t);
12             h[i*(m+1)+j]=t>=d?1:0;
13             sum[i*(m+1)+j]=sum[i*(m+1)+j-1]+sum[(i-1)*(m+1)+j]-sum[(i-1)*(m+1)+j-1]+h[i*(m+1)+j];
14         }
15     int ans,q,a,b,x,y;
16     scanf("%d",&q);
17     while(q--) {
18         ans=0;
19         scanf("%d%d%d%d",&a,&b,&x,&y);
20         ans=sum[x*(m+1)+y]-sum[(a-1)*(m+1)+y]-sum[x*(m+1)+b-1]+sum[(a-1)*(m+1)+b-1];
21         printf("%d\n",ans);
22     }
23     return 0;
24 }

 





posted @ 2019-02-09 15:01  Frontierone  阅读(174)  评论(0编辑  收藏  举报