
二分+贪心
二分确定最终每个人分到的最大值。
注意二分时的下限要设置为一本书的最大页数,否则这本书永远无法分配,则问题无解。
接着从后往前分配页数,由于贪心地使后面大,所以前面有可能分到0,所以,还需要从后往前使没分到的人从分到的人处拿出一张。
输出格式可能有点坑。WA了很多发。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| #include<bits/stdc++.h> using namespace std; typedef pair<int, int> pii; #define ll long long const int INF = 0x3f3f3f3f; const int maxn = 1e5 + 5; ll t, m, k; ll a[505]; bool check(ll x) { ll sum = 0; ll cnt = 1; for (ll i = m; i >= 1; i--) { if (sum + a[i] <= x)sum += a[i]; else { cnt++; sum = a[i]; } if (cnt > k)return false; } return true; } stack<ll>vc[505], st; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> t; while (t--) { cin >> m >> k; ll maxa = 0; for (ll i = 1; i <= m; i++) { cin >> a[i]; maxa = max(maxa, a[i]); } ll L = maxa, R = 5e9 + 10, mid; while (L < R) { mid = (L + R) >> 1; if (check(mid)) { R = mid; } else { L = mid + 1; } } ll sum = 0; ll cnt = 1; for (ll i = m; i >= 1; i--) { if (sum + a[i] <= L) { sum += a[i]; vc[k - cnt + 1].push(a[i]); } else { sum = a[i]; cnt++; vc[k - cnt + 1].push(a[i]); } } ll now = k - cnt + 1; ll rest = k - cnt; while (rest) { if (!vc[now].empty()) { st.push(vc[now].top()); vc[now].pop(); rest--; } if (vc[now].empty()) { rest++; now++; } } ll p = st.size(); while (!st.empty()) { vc[p].push(st.top()); st.pop(); p--; } for (ll i = 1; i <= k; i++) { while (!vc[i].empty()) { ll ans = vc[i].top(); vc[i].pop(); if (i == k && vc[i].empty())cout << ans; else cout << ans << ' '; } if (i != k)cout << "/ "; } cout << endl; } return 0; }
|