巧克力 二分

[Description]

现在有一块1*1*N 的巧克力(每个1*1*1 的部分有一个营养值Ai),想分给K 个小朋友,并且每个小朋友必须得到一整块,即最终只能分成K 块,每个小朋友所得到的营养值即为得到巧克力每部分的营养值之和。

这几个小朋友的自尊心很强,尤其是不允许分得营养值最大的那个人所得的营养值太大。所以,为了照顾好他们,你必须使分得营养值最大的那个人的营养值尽量小。

[Input]

1 行:两个整数N K

2 行:N 个整数Ai,相邻整数用空格隔开

[Output]

一行,分得最多的那个人的最少巧克力

[Sample 1]

chocolate.in

chocolate.out

5 2

2 1 3 4 5

9

样例解释:有如下分法

2 | 1 3 4 5 -> 2 13 -> max=13

2 1 | 3 4 5 -> 3 12 -> max=12

2 1 3 | 4 5 -> 6 9 -> max=9

2 1 3 4 | 5 -> 10 5 -> max=10

再对所有取小min=9

[Hit]

对于30%数据 N <= 30, K <= 10

对于100%数据 N <= 100000, K <= N, Ai <= 10^9

 


第一眼看到这题,我是懵逼,后来知道这题使用二分,再结合它只能整块分的性质,我们就可以写出怎么检查的过程,然后这题就没了。

代码:

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define il inline
#define db double
using namespace std;
il int gi()
{
    int x=0,y=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
    if(ch=='-')
        y=-1;
    ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
    x=x*10+ch-'0';
    ch=getchar();
    }
    return x*y;
}
il ll gl()
{
    ll x=0,y=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
    if(ch=='-')
        y=-1;
    ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
    x=x*10+ch-'0';
    ch=getchar();
    }
    return x*y;
}
int n,k;
ll cho[100045];
il bool check(ll x)
{
    int sum=0;
    ll now=0;
    for(int i=1;i<=n;i++)
    {
    now+=cho[i];
    if(now>x)
    {
        sum++;
        now=cho[i];
    }
    }
    sum++;
    if(sum<=k)
    return 1;
    else
    return 0;
}
ll ans;
void hzr(ll l,ll r)
{
    if(l==r)
    return;
    ll m=(l+r)>>1;
    if(check(m))
    {
    ans=m;
    hzr(l,m);
    }
    else
    {
    hzr(m+1,r);
    }
}
int main()
{
    freopen("chocolate.in","r",stdin);
    freopen("chocolate.out","w",stdout);
    n=gi(),k=gi();
    for(int i=1;i<=n;i++)
    cho[i]=gl();
    hzr(1,100000000000000);
    printf("%lld\n",ans);
    return 0;
}

 

 

 

posted @ 2017-08-27 18:50  GSHDYJZ  阅读(208)  评论(0编辑  收藏  举报