[CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)

Posted COLIN·GAO

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)相关的知识,希望对你有一定的参考价值。

[CodePlus 2017 11月赛&洛谷P4058]木材

Description

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

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

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

Solution

1.因为要求最少几个月,考虑进行二分答案;

2.考虑二分端点。因为有可能已开始就满足需求,所以左端点为0;

3.因为有两个约束条件,一个是总长度,一个是单根要求长度,我们无法确定二分的右端点到底是什么,所以我们需要知道到底哪一个才是真正的约束条件:

我们去比较要求的单根长度和把总任务分配到每一根的需求长度,取最大值就是实际的约束条件;那么二分的右端点实际上就是每棵树长高到约束条件的时间中的最大值,即:

for(i=1;i<=n;++i)if(h[i]<q)maxn=max(maxn,(q-h[i])/a[i]+1);

3.valid函数中验证的过程即为让sum加上所有经过x个月满足单棵树高度约束条件的树的高度,最后与总长度比较即可;

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int h[200200],a[200200];
unsigned long long n,m,s,i,j,k,minn=0,maxn=0,l,r,q;

inline int rd(){
    int x=0;
    bool f=true;
    char c;
    c=getchar();
    while(c<\'0\'||c>\'9\'){
        if(c==\'-\') f=false;
        c=getchar();
    }
    while(c>=\'0\'&&c<=\'9\'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return f?x:-x;
} 

bool valid(unsigned long long x){
    unsigned long long sum=0;
    bool flag=1;
    for(i=1;i<=n;++i)
        if(h[i]+a[i]*x>=minn){
            if(flag)sum+=h[i]+a[i]*x;
            if(sum>=s)return true;
    }
    return false;
}

int main(){
    scanf("%lld%lld%lld",&n,&s,&minn);
    for(i=1;i<=n;++i)h[i]=rd();
    for(i=1;i<=n;++i)a[i]=rd();
    q=max(minn,s/n+1);
    for(i=1;i<=n;++i)if(h[i]<q)maxn=max(maxn,(q-h[i])/a[i]+1);	
    l=0;r=maxn;
    while(l<r){
        unsigned long long mid=(l+r)/2;
        if(valid(mid))r=mid;
        else l=mid+1;
    }
    printf("%lld\\n",l);
    return 0;
}

二分答案的基础参考以前的随笔:http://www.cnblogs.com/COLIN-LIGHTNING/p/8543330.html

以上是关于[CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)的主要内容,如果未能解决你的问题,请参考以下文章

[LOJ 6248]「CodePlus 2017 11 月赛」晨跑

「CodePlus 2017 11 月赛」汀博尔 (二分答案)

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

「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!

「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)

「CodePlus 2017 12 月赛」白金元首与独舞