Code+第一次月赛 B. 汀博尔(二分)

题目描述

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

输入格式

从标准输入读入数据。

第一行 3 个用空格隔开的非负整数 n,S,L,表示树的数量、订单总量和单块木料长度限制。

第二行 n 个用空格隔开的非负整数,依次为 H1,H2,…,Hn。

第三行 n 个用空格隔开的非负整数,依次为 A1,A2,…,An。

输出格式

输出到标准输出。

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

样例1输入

3 74 51
2 5 2
2 7 9

样例1输出

7

Hints

对于样例,在六个月后,各棵树的高度分别为 14,47,56,此时无法完成订单。

在七个月后,各棵树的高度分别为 16,54,65,此时可以砍下第 2 和第 3 棵树完成订单了。

思路

二分月份,然后判断当前月份是否满足条件,注意long long

区间大小是从-1到订单总量到单个木料限制的最大值

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
const ll N=200000+20;
ll a[N],h[N];
ll n,s,limit;
inline ll read()
{
    ll ret=0;
    char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while ('0'<=ch&&ch<='9')
    {
        ret=ret*10-48+ch;
        ch=getchar();
    }
    return ret;
}
ll judge(ll time)
{
    ll sum=0;
    for(ll i=1; i<=n; i++)
    {
        if(limit>h[i]&&time<=(limit-h[i]-1)/a[i])
            continue;
        if(time>=(s-h[i])/a[i])
            return 1;
        sum+=time*a[i]+h[i];
        if(sum>=s)
            return 1;
    }
    return 0;
}
int main()
{
    scanf("%lld%lld%lld",&n,&s,&limit);
    for(ll i=1; i<=n; i++) h[i]=read();
    for(ll i=1; i<=n; i++) a[i]=read();
    ll l=-1,r=max(limit,s);
    while(l+1<r)
    {
        ll mid=(l+r)>>1;
        if(judge(mid))
            r=mid;
        else
            l=mid;
    }
    printf("%lld\n",r);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值