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\n",ans); for(int i=1;i<=n;i++) printf("%d\n",te[i]); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚