典型二分答案+检验题

注意要点:

1、按顺序吃巧克力;

2、巧克力要吃完;

3、二分检验的时候注意看最后一次循环判断的是否是最终的二分答案,如果不是的话在跳出循环之后还得对最终的二分答案进行一次判断(因为吃巧克力的顺序在判断的时候生成,如果最后一次判断的不是最终的二分答案,那么吃巧克力的顺序对应的就不是最终的二分答案)

代码如下:

#include <bits/stdc++.h>
using namespace std;

#define ll long long
const int Nmax = 50000;
int N,D;
int H[Nmax + 5];
int flag[Nmax+5];
bool juage(ll x){
    ll happiness = 0;
    int cur = 1;
    for(int i = 1;i <= D;i++){
        happiness >>= 1;
        while(happiness < x){
            if(cur > N) break;
            else{
                happiness += H[cur];
                flag[cur++] = i;
            }
        }
    }
    //巧克力要吃完
    if(cur <= N)
        for(int j = cur;j <= N;j++)
            flag[j] = D;
    return happiness >= x;
}

int main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    ll l = 0,r = 5e10;
    cin>>N>>D;
    for(int i = 1;i <= N;i++)
        cin>>H[i];
    while(l <= r){
        ll mid = l + (r - l)/2;
        if(juage(mid)) l = mid + 1;
        else r = mid - 1;
    }
    juage(l-1);    //最后一次判断的答案不是最终答案,因此跳出循环之后要用最终答案再判断一次
    //这样生成的flag数组才是最终答案对应的数组
    cout<<l - 1<<'\n';
    for(int i = 1;i <= N;i++)
        cout<<flag[i]<<'\n';
    return 0;
}