Code+ B 汀博尔二分答案

Posted Roni

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Code+ B 汀博尔二分答案相关的知识,希望对你有一定的参考价值。

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

有 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

【分析】:二分答案。上界不能直接选择1e18,会爆long long。根据一棵树能完成需求的时间最小值不断降低时间。
【代码】:
技术分享图片
#include <bits/stdc++.h>
#define LL long long
#define maxn 200005

using namespace std;
LL a[maxn],h[maxn],S,L,mx;
int n;

bool check(LL x)
{
    LL sum=0;
    for(int i=1; i<=n; i++)
        if(x &&log(a[i])+log(x)>log((max(S,L)))) return 1;
    for(int i=1; i<=n; i++)
    {
        LL now = h[i]+a[i]*x;
        if(now>=L) sum+=now;
        if(sum>=S) return 1;
    }
    return 0;
}
int main()
{
    cin>>n>>S>>L;
    for(int i=1;i<=n;i++) cin>>h[i];
    for(int i=1;i<=n;i++) cin>>a[i],mx=max(mx,max(L,S)/a[i]);
    LL l=0,r=mx,ans=0;
    while(l<=r)
    {
        LL mid=(l+r)>>1;
        if(check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans<<endl;
}
View Code

 

技术分享图片
#include<iostream>
#include<set>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

typedef unsigned long long ll;

ll h[2000010],a[2000010];
ll sum;
int main()
{
    ll n,S,L,i,j,l,r,m;
    while(cin>>n>>S>>L)
    {
        l=0;r=1e18;m=(l+r)/2;
        for(i=0;i<n;i++)
            scanf("%d",&h[i]);
        for(i=0;i<n;i++)
            scanf("%d",&a[i]);
        while(l<r)
        {
            sum=0;
            for(i=0;i<n;i++)
            {
                ll x=h[i]+m*a[i];
                if(x>=L)
                     sum+=x;
                if(sum>=S)
                break;
            }
            if(sum>=S)
            {
                r=m;
            }
            else
            {
                l=m+1;
            }
            m=(l+r)/2;
        }
        cout<<m<<"\n";
    }
    return 0;
}
易懂

 

技术分享图片
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
int n;
ll s,l;
ll h[200100],a[200100];
int check(ll mid)
{
    ll sum=0;
    for(int i=1;i<=n;i++)
    {
        if(h[i]+a[i]*mid>=l) sum+=(h[i]+a[i]*mid);
        if(sum>=s) return 1;
    }
    return 0;
}
ll maxx;
int main()
{
    scanf("%d%lld%lld",&n,&s,&l);
    for(int i=1;i<=n;i++) scanf("%lld",&h[i]);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]),maxx=max(maxx,a[i]);
    ll l=0,r=1e18/maxx,mid,ans=0;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(check(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%lld",ans);
}
View Code2

 

以上是关于Code+ B 汀博尔二分答案的主要内容,如果未能解决你的问题,请参考以下文章

bzoj5106 [CodePlus2017]汀博尔 二分

BZOJ5106: [CodePlus2017]汀博尔

[LOJ 6249]「CodePlus 2017 11 月赛」汀博尔

20191006

20190703 B组总结

HDU 6769 In Search of Gold 二分答案+树形DP