https://ac.nowcoder.com/acm/contest/22353/E
有的時候50%通不過真的很無助orz
二分查詢最小幸福值: 我們希望找出一個最大的 mid,即最小幸福值,使得 Bessie 能夠在 d 天內吃完巧克力,並且每天的幸福值都不低於這個 mid。
我們可以透過二分查詢的方式來確定這個 mid。mid 的初始範圍是 [0, 1e12],因為幸福值可能很大。
每次我們計算出 mid 的值後,使用 check() 函式來驗證是否能夠在 d 天內滿足每天的幸福值都不低於 mid。如果可以,我們嘗試增大 mid;如果不行,我們嘗試減小 mid。
注意 如果有剩餘巧克力,需要分配到最後一天,不能有剩餘
- 設定二分查詢的上下界 low = 0, high = 1e12
- 進行二分查詢:
a. 計算 mid = (low + high) / 2
b. 使用 check(mid) 判斷是否可以分配巧克力:
- 如果可以滿足最小幸福值為 mid,更新結果,並嘗試更大的 mid(low = mid + 1)
- 如果不可以滿足,嘗試更小的 mid(high = mid - 1) - 輸出二分查詢的結果(最大最小幸福值)
- 輸出巧克力的分配方案
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, d;
ll a[50050], happiness[50050], ans[50010];
int check(ll mid) {
ll i, j, count, sum, tmp[50010];
count = sum = 1;
happiness[1] = 0;
for(i = 1; i <= d; i++) {
while(happiness[i] < mid) {
if(count > n) return -1; // 巧克力吃完了,返回 -1
tmp[count] = i; // 記錄巧克力被吃掉的天數
happiness[i] += a[count++]; // 增加當前天的幸福值
}
happiness[i + 1] = happiness[i] / 2; // 下一天的幸福值是前一天的一半
}
for(i = 1; i < count; i++) ans[i] = tmp[i]; // 記錄巧克力的分配天數
for(i = count; i <= n; i++) ans[i] = d; // 剩餘巧克力分配到最後一天
return 1;
}
int main() {
cin >> n >> d;
for(int i = 1; i <= n; i++) cin >> a[i];
ll l = 0, r = 1e12;
ll result = 0;
// 二分查詢尋找最大的最小幸福值
while(l <= r) {
ll mid = (l + r) >> 1;
if(check(mid) == 1) result = mid, l = mid + 1;
else r = mid - 1;
}
cout << result << endl;
for(int i = 1; i <= n; i++) cout << ans[i] << endl;
}