积木-蓝桥每日真题

0积木 - 蓝桥云课 (lanqiao.cn)

题目描述
小明用积木搭了一个城堡。
为了方便,小明在搭的时候用的是一样大小的正方体积木,搭在了一个n行m列的方格图上,每个积木正好占据方格图的一个小方格。
当然,小明的城堡并不是平面的,而是立体的。小明可以将积木垒在别的积木上面。当一个方格上的积木垒得比较高时,就是一个高塔,当一个方格上没有积木时,就是一块平地。
小明的城堡可以用每个方格上垒的积木层数来表示。例如,下面就表示一个城堡。
9331
3330
0000
这个城堡南面和东面都有空地,西北面有一个大房子,在西北角还有一个高塔,东北角有一个车库。
现在,格格巫要来破坏小明的城堡,他施了魔法水淹小明的城堡。
如果水的高度为1,则紧贴地面的那些积木要被水淹,在上面的例子中,有7块积木要被水淹。
如果水的高度为2,则更多积木要被水淹,在上面的例子中,有13块积木要被水淹。
给定小明的城堡图,请问,水的高度依次为1,2,3,…,H时,有多少块积木要被水淹。


输入描述
输入的第一行包含两个整数n,m。
接下来n行,每行m个整数,表示小明的城堡中每个位置积木的层数。
接下来包含一个整数H,表示水高度的上限。
其中,便积木层数不超过1e9


输出描述
输出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

#include <iostream>

using namespace std;

const long long N=1e5+10;
long long n,m,H;
long long diff[N];
long long max1;
long long tmp;

int main() {
	// 请在此输入您的代码
	cin >> n >> m;
	for(long long i=0; i<n; i++) {
		for(long long j=0; j<m; j++) {
			long long index;
			cin >> index;
			diff[index]++;
			if(max1 < index) {
				max1 = index;
			}
		}
	}
	for(long long i=1; i<=max1; i++) {
		diff[i]+=diff[i-1];
	}
	cin >> H;
	for(long long i=1; i<=H; i++) {
		tmp += diff[max1] - diff[i-1];
		cout << tmp << endl;

	}
	return 0;
}

思考:

long long diff [ 1e9 + 10]会编译失败,退了一步 写 diff [ 1e5 + 10] ,当输入大于1e5时,处理为1e5,因为水位最大到1e5;以下代码只能过50%,应该是在前缀和的时候爆了,需要优化一下前缀和

优化:

先差分,再前缀和

#include <iostream>

using namespace std;

const long long N=1e5+10;
long long n,m,H;
long long diff[N];
long long max1;
long long ans;

int main()
{
  // 请在此输入您的代码
  cin >> n >> m;

  //构造差分
  for(long long i=0; i<n*m;i++){
      diff[1]++;
      long long index;
      cin >> index;
      if(index > 1e5)index = 1e5;
      diff[index+1]--;
    
  }

  //前缀和
  for(long long i=1;i<=N;i++){
    diff[i]+=diff[i-1];
  }
  cin >> H;
  for(long long i=1;i<=H;i++){
    ans += diff[i];
    cout << ans << endl;
    
  } 
  return 0;
}

  • 27
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值