原题链接:
登录—专业IT笔试面试备考平台_牛客网
题目描述:
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
Bessie has received N (1 <= N <= 50,000) chocolates from the bulls, but doesn't want to eat them too quickly, so she wants to plan out her chocolate eating schedule for the next D (1 <= D <= 50,000) days in order to maximize her minimum happiness level over the set of those days.
Bessie's happiness level is an integer that starts at 0 and halves (rounding down if necessary) over night as she sleeps. However, when she eats chocolate i, her happiness level increases by integer HiH_iHi (1 <= HiH_iHi <= 1,000,000). If she eats chocolates on a day, her happiness for that day is considered the happiness level after she eats the chocolates. Bessie insists that she eat the chocolates in the order that she received them.
If more than one optimal solution exists, print any one of them.
Consider a sequence of 5 chocolates to be eaten over a period of 5 days; they respectively bring happiness (10, 40, 13, 22, 7).If Bessie eats the first chocolate (10 happiness) on the first day and then waits to eat the others, her happiness level is 10 after the first day.
Here is the complete schedule which turns out to maximize her minimum happiness: Day Wakeup happiness Happiness from eating Bedtime happiness 1 0 10+40 50 2 25 --- 25 3 12 13 25 4 12 22 34 5 17 7 24 The minimum bedtime happiness is 24, which turns out to be the best Bessie can do.输入描述:
* Line 1: Two space separated integers: N and D * Lines 2..N+1: Line i+1 contains a single integer: HiH_iHi输出描述:
* Line 1: A single integer, the highest Bessie's minimum happiness can be over the next D days * Lines 2..N+1: Line i+1 contains an integer that is the day on which Bessie eats chocolate i输入
5 5 10 40 13 22 7输出
24 1 1 3 4 5
题目大意:
解题思路:
典型的二分+检验答案。最大化最小值问题。
我们可以假设最小快乐指数,然后检查这个假设的快乐指数是否可达,检查的方式是每天如果快乐值足够,就不吃巧克力,否则吃一块,如果巧克力吃完了还不能达到假定的快乐指数,则这个快乐指数是不可达的。
提供两种二分的写法,具体细节看代码和注释。
代码1(CPP):
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 5e4 + 100;
const int INF = 0x3fffffff;
const int mod = 1000000007;
ll n, d, h[maxn], ans[maxn];
bool check(ll x) {
ll v = 0;
int p = 1;
for (int i = 1; i <= d; i++) {
v /= 2;
while (v < x && p <= n) {
v += h[p];
ans[p] = i;
p++;
}
if (v < x) {
return false;
}
}
for (; p <= n; p++) { // 坑点,所有巧克力都必须吃完,所以如果最后有剩下的必须吃掉
ans[p] = d;
}
return true;
}
void solve() {
cin >> n >> d;
ll l = 0, r = 0, k;
for (int i = 1; i <= n; i++) {
cin >> h[i];
r += h[i];
}
while (l < r) { // 写法一,不抛弃mid
ll mid = (l + r + 1) / 2; // 特别注意,不抛弃mid的写法求最大化最小值时,mid=(l+r+1)/2
if (check(mid)) {
l = mid;
} else {
r = mid - 1;
}
}
k = l;
check(k); // 坑点,最后二分完毕之后,,ans数组里不一定是答案的状态
cout << k << endl;
for (int i = 1; i <= n; i++) {
cout << ans[i] << endl;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout << fixed;
cout.precision(18);
solve();
return 0;
}
代码2(CPP):
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 5e4 + 100;
const int INF = 0x3fffffff;
const int mod = 1000000007;
ll n, d, h[maxn], ans[maxn];
bool check(ll x) {
ll v = 0;
int p = 1;
for (int i = 1; i <= d; i++) {
v /= 2;
while (v < x && p <= n) {
v += h[p];
ans[p] = i;
p++;
}
if (v < x) {
return false;
}
}
for (; p <= n; p++) { // 坑点,所有巧克力都必须吃完,所以如果最后有剩下的必须吃掉
ans[p] = d;
}
return true;
}
void solve() {
cin >> n >> d;
ll l = 0, r = 0, k;
for (int i = 1; i <= n; i++) {
cin >> h[i];
r += h[i];
}
while (l <= r) { // 写法二,抛弃mid
ll mid = (l + r) / 2;
if (check(mid)) {
// 或者也可以在这里记录答案 k = mid
l = mid + 1;
} else {
r = mid - 1;
}
}
k = l - 1; // 注意这种写法这里的答案不应该是l,应该是l - 1
check(k); // 坑点,最后二分完毕之后,,ans数组里不一定是答案的状态
cout << k << endl;
for (int i = 1; i <= n; i++) {
cout << ans[i] << endl;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout << fixed;
cout.precision(18);
solve();
return 0;
}