【ZCMU2027】汀博尔(二分)

针对汀博尔问题,本文详细介绍了如何通过二分查找法来确定满足特定订单所需的最小等待月份数。考虑到树木生长速度及订单对木材长度的要求,文章提供了一个高效的解决方案。

题目链接

2027: 汀博尔

Time Limit: 1 Sec  Memory Limit: 512 MB
Submit: 159  Solved: 38
[Submit][Status][Web Board]

Description

 

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

Input

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

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

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

Output

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

Sample Input

3 74 51

2 5 2

2 7 9

Sample Output

7

HINT
 

测试点编号nnn特殊约定
1n=1n = 1n=11≤S≤Hi≤100001 \leq S \leq H_i \leq 100001≤S≤Hi≤10000
21≤S,L,Hi,Ai≤100001 \leq S, L, H_i, A_i \leq 100001≤S,L,Hi,Ai≤10000
31≤n≤10001 \leq n \leq 10001≤n≤1000
4
5
61≤S,L,Hi,Ai≤1091 \leq S, L, H_i, A_i \leq 10^91≤S,L,Hi,Ai≤109
7
8
91≤n≤200001 \leq n \leq 200001≤n≤20000
10
111≤S,L≤10181 \leq S, L \leq 10^{18}1≤S,L≤1018,1≤Hi,Ai≤1091 \leq H_i, A_i \leq 10^91≤Hi,Ai≤109
12
131≤n≤2000001 \leq n \leq 2000001≤n≤200000L=1L = 1L=1
14S≤LS \leq LS≤L
151≤S,L≤10181 \leq S, L \leq 10^{18}1≤S,L≤1018,1≤Hi,Ai≤1091 \leq H_i, A_i \leq 10^91≤Hi,Ai≤109
16
17
18
19
20

 

 

解题思路:

刚开始想都没想直接暴力WA了一发,其实看数据这么大就应该要想到二分了的,这题有个坑点S,L的大小是不一定的,记得考虑。然后就是二分查找月份的问题了,这里需要考虑一下上界的问题,最差的情况就是一棵树刚刚长到max(S,L),这样就没别的树什么事了,所以上界r=min(r,(t-h[i])/a[i]+1)。

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=200005;
LL h[maxn],a[maxn],s,l,n;
int check(LL x)
{
    LL sum=0,y=0;
    for(int i=0;i<n;i++)
    {
        y=h[i]+a[i]*x;
        if(y>=l)sum+=y;
    }
    if(sum>=s)return 1;
    else return 0;
}
int main()
{
    LL t,ans=0;
    scanf("%lld%lld%lld",&n,&s,&l);
    t=max(s,l);
    for(int i=0;i<n;i++)
        scanf("%lld",&h[i]);
    for(int i=0;i<n;i++)
        scanf("%lld",&a[i]);
    LL l=0,r=1e18,mid;
    for(int i=0;i<n;i++)
        r=min(r,(t-h[i])/a[i]+1);
    while(l<=r)
    {
        mid=(l+r)/2;
        if(check(mid))
        {
            r=mid-1;
            ans=mid;
        }
        else l=mid+1;
    }
    printf("%lld\n",ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值