二分例题

链接:https://ac.nowcoder.com/acm/problem/14504
来源:牛客网

题目描述
有 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
输出
复制
7
说明
对于样例,在六个月后,各棵树的高度分别为 14,47,56,此时无法完成订单。
在七个月后,各棵树的高度分别为 16,54,65,此时可以砍下第 2 和第 3 棵树完成订单了。
备注:
1≤n≤200000,1≤S,L≤1018,1≤Hi,Ai≤109
二分具体看代码吧,也有注释,我太菜了,看了大佬代码才会的。。。。。。。

//https://ac.nowcoder.com/acm/problem/14504
//二分,利用范围是0到最大月份,但为了避免出现界限不够问题,最好多开一位,比如这道题,
//当增长数组大于 max(要的木材和最小量) ,不多开的话,很可能输出0,实际是1年 
#include
using namespace std;
#define ll long long
const int N=2e5+20;
ll q[N],a[N]; 
ll n,lll,s;
bool check(ll mid)//二分的判断函数,利用月份 
{
    ll sum=0,x;
    for(int i=0;i<n;i++)
    {
        x=q[i]+a[i]*mid;
        if(x<lll) continue;//判断这个月份的树合适不 
        sum+=x;
        if(sum>=s) return true; 
    }
    return false;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    ll t,r=0,l=0;
    cin>>n>>s>>lll;
    for(int i=0;i>q[i];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        r=max(r,a[i]);
    }
    r=max(s,lll)/r+1;////当增长数组大于 max(要的木材和最小量) ,不多开的话,很可能输出0,实际是1年  
    while(l<r)//套板子开始了 
    {
        ll mid=l+r>>1;//注意用ll,我当初用的int,然后暴了,最后显示超时 
        if(check(mid)) r=mid;
        else l=mid+1; 
    }
    cout<<l<<endl;
    return 0;
}
全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务