BZOJ2016: [Usaco2010 Feb]Chocolate Eating

【传送门:BZOJ2016


简要题意:

  贝西收到了N 块巧克力,她会在接下来的D 天里吃掉这些巧克力,她想制定一个计划,让她每 天的快乐度都保持在较高的水品上。 在第一天刚开始的时候,贝西的快乐度为0。巧克力必须从第一块吃起,不能打乱食用的次序, 因为公牛们是按照这个顺序送给她的。吃掉第i 块巧克力,会让她的快乐度立即增加Ai。贝西在一天 内可以连续食用多块巧克力,也可以一块也不吃。不管如何,当她晚上睡觉之后,快乐度会在半夜减 半,如果快乐度是个奇数,则向下取整。请问贝西应该怎样吃巧克力,才能让她在D 天内最小快乐 度最大呢?


输入格式:

  • 第一行:两个整数N 和D,1 ≤ N;D ≤ 50000

  • 第二行到第N + 1 行:第i + 1 行有一个整数Hi,1 ≤ Hi ≤ 10^6


输出格式:

  • 单个整数:表示贝西在D 天内的最小快乐度的最大值

  • 下来n行输出每个巧克力在哪一天吃掉


样例输入:

5 5

10

40

13

22

7


样例输出:

24

1

1

3

4

5


样例解释:

  第一天吃前两块巧克力,第二天一块都不吃, 接下来三天每天各吃一块。


题解:

  也是二分最小最大值

  然后就一天一天的走,每当当前的欢乐值小于二分的值时,就不停地吃巧克力直到大于等于二分的值(记得开long long)


参考代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long LL;
LL a[51000];int n,d;
int b[51000],te[51000];
bool check(LL x)
{
    memset(b,0,sizeof(b));
    LL sum=0;
    int t=1;
    for(int i=1;i<=d;i++)
    {
        sum/=2;
        while(sum<x&&t<=n)
        {
            sum+=a[t];
            b[t]=i;
            t++;
        }
        if(sum<x) return false;
    }
    return true;
}
int main()
{
    scanf("%d%d",&n,&d);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    LL l=0LL,r=50000000000LL;
    LL ans=0LL;
    while(l<=r)
    {
        LL mid=(l+r)/2LL;
        if(check(mid)==true)
        {
            for(int i=1;i<=n;i++)
            {
                if(b[i]==0) te[i]=d;
                else te[i]=b[i];
            }
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    printf("%lld
",ans);
    for(int i=1;i<=n;i++) printf("%d
",te[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/Never-mind/p/7764827.html