AcWing 730. 机器人跳跃问题(典型二分答案求满足条件的最小值)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题意:

机器人初始能量为E,下一个建筑高 H,如果当前能量大于H,那么跳到下一个建筑的能量变为 E + (E-H),否则能量为E-(H-E),其实两种情况可以归结为一种情况2E - H,目标是到达第N个建筑,且 在这个过程中能量值不能为负数,问机器人初始能量E最少为多少?

思路:

对于 “最少/最大是多少” 这类问题,可以想一想是否能用二分来做

那么如何确定是否能用二分呢?

回顾一下二分的具体步骤

步骤① 判断 是否具有二段性的性质,或者 单调性(如果一个题目具有单调性那么一定可以用二分,如果不具有单调性有时候也可以用二分,二段性 “包含” 单调性,单调性是二段性的子集

  • 判断这道题是否具有单调性:如果初始能量E0能够满足要求(中间过程非负),那么E'≥E0时,是否也能够满足要求?

  • 根据题意,显然E0成立之时,所有E'≥E0的值是成立的,这样的话是具有单调性的,所以E0一定是个最小的值,且可以二分

在这里插入图片描述

  • 如上图,如果E0是满足条件的,那么其后面阴影部分必然都是满足条件的,有单调性就一定具有二段性,我们可以用二分来做本题。

  • 二段的性质:某一个能量E是否可以满足条件?

  • 判断条件check初始值如果是E0,那么中间过程是否都是≥0的?

  • 我们运用这个判断条件一定二分出答案。

步骤② 考虑二分的形式(划分的方案是 r=mid or l=mid

  • 设检查E是否成立的函数叫做check函数,if(check(mid))(成立),说明 初始能量E0如果是mid时,是满足要求的,那么 如果mid满足要求所有≥mid的阴影部分值都满足要求(根据 单调性)。如下图

在这里插入图片描述

  • 我们查找的目标值最小满足要求的值(注意目标值),显然 目标值在mid及其左部分,即[L, mid]mid可能为答案),所以我们在更新区间的时候应该“r=mid”,对应下图是红色部分
    在这里插入图片描述

  • 如果mid不满足要求,那么意味着 所有≤mid的部分都不满足要求mid也不满足要求,所以答案在[mid+1, R]中,所以我们在更新区间的时候应该“l=mid+1

  • 所以有:

int mid = l+r>>1;//由于是r=mid,所以不需要+1
if(check(mid)) r = mid;
else l = mid+1;

步骤③ 考虑如何书写check函数(判断机器人每一步跳跃是否恒≥0

  • 我们发现每一项都可以由前面一项递推出来,所以我们只需从前往后递推一遍,判断中间有没有出现负数,如果中间过程没有出现过负数那么返回true否则返回false

  • 注意在中间递推过程中,由于不断×2,可能会出现超过1e5的情况,此时直接返回true即可!

时间复杂度:

O(nlogn)

代码:

#include<bits/stdc++.h>

using namespace std;
const int N = 1e5+10;
int a[N];
int n;

bool check(int mid)
{
    for(int i=0;i<n;++i)
    {
        mid = 2*mid - a[i];
        if(mid<0) return false;
        if(mid>=1e5) return true;//中间过程可能爆掉1e5,因此一旦爆掉直接返回true
    }
    return true;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;++i)
    {
        scanf("%d", &a[i]);
    }
    int l = 1, r = 1e5;
    while(l<r)
    {
        int mid = l+r>>1;
        if(check(mid)) r = mid;
        else l = mid+1;
    }
    cout<<l<<endl;
    
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值