积木
题目描述
小明用积木搭了一个城堡。
为了方便,小明在搭的时候用的是一样大小的正方体积本,搭在了一个 n 行 m 列的方格图上,每个积木正好占据方格图的一个小方格。
当然,小明的城堡并不是平面的,而是立体的。小明可以将积木垒在别的积木上面。当一个方格上的积木垒得比较高时,就是一个高塔,当一个方格上没有积木时,就是一块平地。
小明的城堡可以用每个方格上垒的积木层数来表示。例如,下面就表示一个城堡。
9 3 3 1
3 3 3 0
0 0 0 0
这个城堡南面和东面都有空地,西北面有一个大房子,在西北角还有一个高塔,东北角有一个车库。
现在,格格巫要来破坏小明的城堡,他施了魔法水淹小明的城堡。
如果水的高度为 1,则紧贴地面的那些积木要被水淹,在上面的例子中,有 7 块积木要被水淹。
如果水的高度为 2,则更多积木要被水淹,在上面的例子中,有 13 块积木要被水淹。
给定小明的城堡图,请问,水的高度依次为 1,2,3,⋯,H 时,有多少块积木要被水淹。
输入描述
输入的第一行包含两个整数 n,m。
接下来 n 行,每行 m 个整数,表示小明的城堡中每个位置积木的层数。
接下来包含一个整数 H,表示水高度的上限。
输出描述
输出 H 行,每行一个整数。第 i 的整数表示水的高度为 i时被水淹的积木数量。
输入输出样例
示例
输入
3 4
9 3 3 1
3 3 3 0
0 0 0 0
10
输出
7
13
19
20
21
22
23
24
25
25
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
总通过次数: 565 | 总提交次数: 922 | 通过率: 61.3%
难度: 中等 标签: 2020, 模拟, 省模拟赛
思路分享:
首先通过时间复杂度可以看出,暴力破解的话是O(n^3),并且题目有说H的范围最大为10^5。时间会运行超时。
所以采用差分和前缀和的方式降低时间复杂度。
前缀和和差分还不太熟的小伙伴可以传送过去学习。
代码分享:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N=1010,M=100010;
int g[N][N];
int n,m,h;
long long s[M];//差分
void insert(int l,int r)
{
s[l]+=1;
s[r+1]-=1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
cin>>g[i][j];
if(g[i][j]>0&&g[i][j]<=100000) insert(1,g[i][j]);
}
cin>>h;
for(int i=1;i<=h;i++) s[i]+=s[i-1];
for(int i=1;i<=h;i++) {s[i]+=s[i-1]; cout<<s[i]<<endl; }
return 0;
}