典型二分答案+检验题
注意要点:
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;
}