(蓝桥真题)青蛙过河(思维+双指针/二分)

样例输入: 

5 1
1 0 1 0

样例输出:

4

分析:首先去和回是没有区别的,所以我们直接考虑是去2*x次即可

结论:假如说跳跃能力是c,那么对于任何一个长度为c的区间中的石头总高度都不能小于2*x。且当所有区间中的石头高度都大于等于2*x时,一定可以通过2*x次

证明:

先证明必要性:

如果要是存在某个长度为c的区间的石头总高度小于2*x,那么也就是说落到这个区间上石头的次数是小于2*x的,那么也就是必然会有几次是不经过这个区间的,但是由于这个区间长度为c,想要不经过这个区间直接跳过去那么弹跳能力显然要大于c,所以这是不可能的

下面证明充分性:

我们假设2*x只青蛙同时跳到区间1~c上的石头,那么现在我们考虑使1位置上的青蛙跳到第c+1个位置,如果要是h[1]<=h[c+1],那么这个显然是可以实现的,但是如果要是h[1]>h[c+1],那么我们需要分析一下,因为h[2]+h[3]+……+h[c+1]>=2*x,则h[2]+h[3]+……+h[c]>=2*x-h[c+1],那么我们就有h[1]+h[2]+h[3]+……+h[c]>=2*x+h[1]-h[c+1],我们可以把h[1]中的h[1]-h[c+1]调整至2~c块石头上,这样第一块石头上的青蛙个数就不会大于第c+1块石头上的青蛙,那么这样我们就能使得青蛙转移到2~c+1上,同理我们可以完成3~c+2上的转换……,这样我们就证明了结论的充分性

代码实现的话可以用双指针直接找出来满足所有区间和大于等于2*x的最小区间长度,复杂度是O(n),这个也是本博客使用的方法

还有一种方法就是直接二分长度然后判断是否可行,实现比较简单,复杂度是O(nlogn)

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=1e5+10;
long long h[N];
int main()
{
	long long n,x;
	cin>>n>>x;
	x<<=1;
	for(int i=1;i<n;i++)
		scanf("%lld",&h[i]);
	long long ans=0,s=0;
	for(int i=0,j=0;j<=n;)
	{
		while(j<=n&&s<x)
			s+=h[j++];
		ans=max(ans,min(1ll*j,n)-i);
		s-=h[i++];
	}
	printf("%lld",ans);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值