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

AcWing 730. 机器人跳跃问题(典型二分答案求满足条件的最小值)_第1张图片
AcWing 730. 机器人跳跃问题(典型二分答案求满足条件的最小值)_第2张图片
AcWing 730. 机器人跳跃问题(典型二分答案求满足条件的最小值)_第3张图片
题意:

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

思路:

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

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

回顾一下二分的具体步骤

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

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

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

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

  • 如上图,如果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

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

bool check(int mid)
{
    for(int i=0;i=1e5) return true;//中间过程可能爆掉1e5,因此一旦爆掉直接返回true
    }
    return true;
}

int main()
{
    cin>>n;
    for(int i=0;i>1;
        if(check(mid)) r = mid;
        else l = mid+1;
    }
    cout<

你可能感兴趣的:(基础算法,二分,算法,数据结构)