Chocolate Eating【二分】

题目链接:https://ac.nowcoder.com/acm/contest/1577/K

题目大意:

给出n块巧克力,m天吃完。每块巧克力有a[i]快乐值,每天可以选择吃任意块或者不吃巧克力(按照给出的巧克力顺序吃),求如何吃巧克力可以使快乐值的最小值最大。

题解思路:

1.二分最小的开心值。check检查是否有方案可以使得每天的快乐值大于当前的mid,若存在,则答案可以增大,即l = mid + 1。若不存在,则答案减小,即r = mid - 1。

2.对于最后得出来的答案,再进行一次get()函数,得到每块巧克力在第几天被吃。而没有被吃到的巧克力全都在最后一天吃完。

代码如下:

 1 #include<stdio.h>
 2 typedef long long ll;
 3 const int MAXN = 5e4 + 100;
 4 
 5 int n, m, day[MAXN];//n块 m天吃完 
 6 ll l, r, mid, a[MAXN], ans;
 7 
 8 int check(ll x) //每天都要达到x这么多的开心值 
 9 {
10     ll sum = 0; //每天的开心值 
11     int k = 0; //巧克力编号 
12     for(int i = 1; i <= m; i ++)
13     {
14         sum /= 2;  //每天都折半 
15         while(sum < x)  //必须满足该天的开心值大于x 
16         {
17             k ++;
18             sum += a[k];
19             if(k > n) //若无法满足 
20                 return 0;
21         }
22     }
23     return 1;
24 }
25 
26 void get(ll x)
27 {
28     ll sum = 0;
29     int k = 0;
30     for(int i = 1; i <= m; i ++)
31     {
32         sum /= 2;
33         while(sum < x)
34         {
35             k ++;
36             sum += a[k];
37             day[k] = i; //第k个巧克力在第几天吃 
38         }
39     }
40 }
41 
42 int main()
43 {
44     scanf("%d%d", &n, &m);
45     for(int i = 1; i <= n; i ++)
46     {
47         scanf("%lld", &a[i]);
48         r += a[i];
49     }
50     while(l <= r)
51     {
52         mid = (l + r) / 2;
53         if(check(mid))
54         {
55             l = mid + 1;
56             ans = mid;
57         }
58         else
59             r = mid - 1;
60     }
61     printf("%lld
", ans);
62     get(ans);
63     for(int i = 1; i <= n; i ++)
64     {
65         if(day[i])
66             printf("%d
", day[i]);
67         else
68             printf("%d
", m);
69     }
70     return 0;
71 }
View Code
原文地址:https://www.cnblogs.com/yuanweidao/p/11789425.html