二分——汀博尔

题目链接

二分——汀博尔

题目描述

有 n 棵树,初始时每棵树的高度为 Hi,第 i 棵树每月都会长高 Ai。现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于 L,而且木料必须是整棵树(即不能为树的一部分)。现在问你最少需要等多少个月才能满足订单。

输入描述

第一行 3 个用空格隔开的非负整数 n,S,L,表示树的数量、订单总量和单块木料长度限制。
第二行 n 个用空格隔开的非负整数,依次为 H1,H2,… ,Hn
第三行 n 个用空格隔开的非负整数,依次为 A1,A2,… ,An

输出描述

输出一行一个整数表示答案。

示例

输入

3 74 51
2 5 2
2 7 9

输出

7

说明

对于样例,在六个月后,各棵树的高度分别为 14,47,56,此时无法完成订单。
在七个月后,各棵树的高度分别为 16,54,65,此时可以砍下第 2 和第 3 棵树完成订单了。

备注

1 ≤ n ≤ 200000,1 ≤ S,L ≤ 1018,1 ≤ Hi,Ai ≤ 109

分析

这题我们可以将需要等的月数进行二分查找,但需要注意一下二分边界。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
ll n,s,l,h[maxn],a[maxn],f[maxn],mx=-1;

int check(ll mid)
{
	for(int i=0;i<n;i++){
		f[i]=h[i]+mid*a[i];		// mid 月后每棵树的高度 
	}
	ll sum=0; 
	for(int i=0;i<n;i++){
		if(f[i]>=l){	// 当树的高度大于等于 l 时,更新 sum 值 
			sum+=f[i];
		}
		if(sum>=s){
			return 1;
		}
	}
	return 0;
}

int main()
{
	cin>>n>>s>>l;
	for(int i=0;i<n;i++){
		cin>>h[i];
	}
	for(int i=0;i<n;i++){
		cin>>a[i];
		mx=max(mx,a[i]);
	}
	ll l=0,r=1e18/mx+1;	// 左右边界 
	while(l<=r){
		ll mid=(l+r)/2;
		if(check(mid)){
			r=mid-1;
		}
		else{
			l=mid+1;
		}
	}
	cout<<l<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值