北湖挖坑 | 感受算法的魅力

4. 北湖挖坑

成绩10开启时间2020年09月7日 星期一 09:00
折扣0.8折扣时间2020年09月15日 星期二 09:00
允许迟交关闭时间2020年10月10日 星期六 23:00

Description

十一年前,北湖曾经是一片平整的土地,北湖的施工队打算将其挖出深坑,注水造出人工湖。

为了简化运算,我们假设北湖的地面是一维的,每一块宽度都为1,高度是非负整数,那么可以用一个数组来表达一块地面。

一开始北湖是一片平地,每一块的高度为h。下图是h=3的情况,用数组表示为[3,3,3,3,3,3,3,3,3,3,3,3]。

施工队根据图纸想将其挖成凹凸不平的形状,如下图所示,数组表示为[0,1,0,2,1,0,1,3,2,1,2,1]。

施工队有一台挖土机,每一天挖土机可以将连续一段区间挖掉一格土。包工头小张想尽快完成任务,请你告诉他将平整的土地挖成图纸所示的情况最少需要多少天?

Input

第一行输入两个整数n(1 \leq n \leq 100000 ),h(1 \leq h \leq 1000000 )。表示北湖的总宽度和初始每一块的高度。

接下来一行n个整数a_i (0 \leq a_i \leq h ),表示图纸上每一个位置的高度。

Output

一个整数表示最少几天能将北湖挖好。

Notes

9天挖土的区间为[1,7],[1,3],[5,7],[1,1],[3,3],[6,6],[9,12],[10,10],[12,12]。

 

 测试输入期待的输出时间限制内存限制额外进程
测试用例 1以文本方式显示
  1. 12 3↵
  2. 0 1 0 2 1 0 1 3 2 1 2 1↵
以文本方式显示
  1. 9↵
1秒64M0

       这题暴力、二分都会 tle(超时),那我们需要更聪明的办法,让我们代码的时间复杂度降低:

       对于题中给出的用例,我们需要挖掉的部分如图:

       为了方便思考,我们将上图倒过来考虑,不用担心,这样考虑结果肯定是一样的。每一处需要挖去的高度可以计算存储入数组:[3, 2, 3, 1, 2, 3, 2, 0, 1, 2, 1, 2]。

       我们最开始将施工天数设定为第一块需要挖去的高度。如上图 days = 3。

       接着,我们第二块开始,从左至右依次考虑:

  • 如果当前需要挖去的高度比前一块低,那么这一块的施工时间可以在之前一并完成(每一天挖土机可以将连续一段区间挖掉一格土),我们在当前这一块不需要加时
  • 如果当前需要挖去的高度比前一天高,那么我们需要加时,days += 两者高度差。

       比如上面的用例,我们的算法过程如图:

方法很简单,就是这个思维方式很难想到。代码也没啥难度,直接上代码了:

哦对,记得把数据类型都用 long long int,不然可能由于数字溢出而 wa...

#include <stdio.h>

#define LEN 100005

long long h[LEN];  //每一处需要挖去的高度

int main() {
    long long wid, height;
    scanf("%lld %lld", &wid, &height);

    for(long long i = 0; i < wid; i++) {
        long long cur;
        scanf("%lld", &cur);  //输入最终要求的高度
        h[i] = height - cur;  //计算每一处需要挖去的高度
    }

    long long ans = h[0];  //初始天数
    for(long long i = 1; i < wid; i++) {
        if(h[i] > h[i - 1]) 
            ans += h[i] - h[i - 1];  //加时
    }

    printf("%lld\n", ans);
}


欢迎关注个人公众号 鸡翅编程 ”,这里是认真且乖巧的码农一枚。

---- 做最乖巧的博客er,做最扎实的程序员 ----

旨在用心写好每一篇文章,平常会把笔记汇总成推送更新~

在这里插入图片描述

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值