// clang-format off
#include<bits/stdc++.h>
using namespace std;
using LL=long long;
#define FOR(i,l,r) for(auto i=(l);i<=(r);++i)
#define REP(i,n) FOR(i,0,(n)-1)
#define ssize(x) int(x.size())
template<class A,class B>auto&operator<<(ostream&o,pair<A,B>p){return o<<"("<<p.first<<", "<<p.second<<")";}
template<class T>auto operator<<(ostream&o,T x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<(", ")+2*!i++<<e;return o<<"}";}
#ifdef DEBUG
#define debug(X...)cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<"\n";}(X)
#else
#define debug(...) {}
#endif
// clang-format on
int N, ncoins, votes_needed;
vector<int> greeds;
vector<int> will_get;
vector<int> proposal;
bool
backtrack(int pirate, int left_to_give, int voted)
{
// Finish
if (pirate >= N) return voted >= votes_needed;
// Pirate must vote, otherwise he would be thrown out
if (will_get[pirate] == -1) {
proposal[pirate] = 0;
return backtrack(pirate + 1, left_to_give, voted + 1);
}
// We discard this pirate
if (backtrack(pirate + 1, left_to_give, voted)) {
proposal[pirate] = 0;
return true;
}
// We must satisfy this pirate
const auto& takes = will_get[pirate] + greeds[pirate];
if (takes <= left_to_give
&& backtrack(pirate + 1, left_to_give - takes, voted + 1))
{
proposal[pirate] = takes;
return true;
}
// Failure
return false;
}
int
choose_proposal2(int n)
{
int l = 0, r = ncoins;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (backtrack(n + 1, ncoins - mid, 0))
l = mid;
else
r = mid - 1;
}
return r;
}
int
choose_proposal(int n)
{
// Calculate dp
const int INF = numeric_limits<int>::max() - 100 - 5000000;
vector<vector<pair<int, bool>>> dp(
N - n + 1, vector<pair<int, bool>>(N - n + 1, {INF, true}));
dp.back()[0] = {0, false};
for (int i = N - 1; i > n; --i) {
auto& cdp = dp[i - n];
const auto& odp = dp[i + 1 - n];
cdp[0] = {0, false};
// Case 1: we must vote
if (will_get[i] == -1) {
FOR (v, 1, ssize(cdp) - 1) cdp[v] = odp[v - 1];
continue;
}
// Case 2: we discard this guy
FOR (v, 0, ssize(cdp) - 1) {
cdp[v].first = odp[v].first;
cdp[v].second = false; // we didn't vote
}
// Case 3: we vote with this guy
FOR (v, 1, ssize(cdp) - 1) {
cdp[v]
= min(cdp[v], {odp[v - 1].first + will_get[i] + greeds[i], true});
}
debug(i, cdp);
}
// Find best sum
int vote = 0;
pair<int, bool> start = {INF, true};
FOR (v, votes_needed, ssize(dp[0]) - 1) {
if (dp[1][v] < start) {
vote = v;
start = dp[1][v];
}
}
if (start.first > ncoins) return -1;
// Generate proposal
proposal[n] = ncoins - start.first;
FOR (i, n + 1, N - 1) {
const auto& cdp = dp[i - n][vote];
if (will_get[i] == -1)
--vote, proposal[i] = 0;
else if (cdp.second)
proposal[i] = will_get[i] + greeds[i], --vote;
else
proposal[i] = 0;
}
return proposal[n];
}
int
main()
{
cin.tie(0)->sync_with_stdio(0);
cin >> N >> ncoins;
greeds.resize(N);
for (auto& g : greeds) cin >> g;
debug(greeds);
will_get.resize(N), proposal.resize(N);
will_get.back() = greeds.back();
for (int n = N - 2; n >= 0; --n) {
debug("START", n);
votes_needed = (N - 1 - n) / 2;
int my_take = choose_proposal(n);
if (my_take == -1) {
will_get[n] = -1;
} else {
proposal[n] = my_take;
swap(will_get, proposal);
}
debug(n, my_take, will_get);
}
REP (i, N) cout << will_get[i] << " ";
cout << "\n";
return 0;
}
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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | // clang-format off #include<bits/stdc++.h> using namespace std; using LL=long long; #define FOR(i,l,r) for(auto i=(l);i<=(r);++i) #define REP(i,n) FOR(i,0,(n)-1) #define ssize(x) int(x.size()) template<class A,class B>auto&operator<<(ostream&o,pair<A,B>p){return o<<"("<<p.first<<", "<<p.second<<")";} template<class T>auto operator<<(ostream&o,T x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<(", ")+2*!i++<<e;return o<<"}";} #ifdef DEBUG #define debug(X...)cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<"\n";}(X) #else #define debug(...) {} #endif // clang-format on int N, ncoins, votes_needed; vector<int> greeds; vector<int> will_get; vector<int> proposal; bool backtrack(int pirate, int left_to_give, int voted) { // Finish if (pirate >= N) return voted >= votes_needed; // Pirate must vote, otherwise he would be thrown out if (will_get[pirate] == -1) { proposal[pirate] = 0; return backtrack(pirate + 1, left_to_give, voted + 1); } // We discard this pirate if (backtrack(pirate + 1, left_to_give, voted)) { proposal[pirate] = 0; return true; } // We must satisfy this pirate const auto& takes = will_get[pirate] + greeds[pirate]; if (takes <= left_to_give && backtrack(pirate + 1, left_to_give - takes, voted + 1)) { proposal[pirate] = takes; return true; } // Failure return false; } int choose_proposal2(int n) { int l = 0, r = ncoins; while (l < r) { int mid = (l + r + 1) >> 1; if (backtrack(n + 1, ncoins - mid, 0)) l = mid; else r = mid - 1; } return r; } int choose_proposal(int n) { // Calculate dp const int INF = numeric_limits<int>::max() - 100 - 5000000; vector<vector<pair<int, bool>>> dp( N - n + 1, vector<pair<int, bool>>(N - n + 1, {INF, true})); dp.back()[0] = {0, false}; for (int i = N - 1; i > n; --i) { auto& cdp = dp[i - n]; const auto& odp = dp[i + 1 - n]; cdp[0] = {0, false}; // Case 1: we must vote if (will_get[i] == -1) { FOR (v, 1, ssize(cdp) - 1) cdp[v] = odp[v - 1]; continue; } // Case 2: we discard this guy FOR (v, 0, ssize(cdp) - 1) { cdp[v].first = odp[v].first; cdp[v].second = false; // we didn't vote } // Case 3: we vote with this guy FOR (v, 1, ssize(cdp) - 1) { cdp[v] = min(cdp[v], {odp[v - 1].first + will_get[i] + greeds[i], true}); } debug(i, cdp); } // Find best sum int vote = 0; pair<int, bool> start = {INF, true}; FOR (v, votes_needed, ssize(dp[0]) - 1) { if (dp[1][v] < start) { vote = v; start = dp[1][v]; } } if (start.first > ncoins) return -1; // Generate proposal proposal[n] = ncoins - start.first; FOR (i, n + 1, N - 1) { const auto& cdp = dp[i - n][vote]; if (will_get[i] == -1) --vote, proposal[i] = 0; else if (cdp.second) proposal[i] = will_get[i] + greeds[i], --vote; else proposal[i] = 0; } return proposal[n]; } int main() { cin.tie(0)->sync_with_stdio(0); cin >> N >> ncoins; greeds.resize(N); for (auto& g : greeds) cin >> g; debug(greeds); will_get.resize(N), proposal.resize(N); will_get.back() = greeds.back(); for (int n = N - 2; n >= 0; --n) { debug("START", n); votes_needed = (N - 1 - n) / 2; int my_take = choose_proposal(n); if (my_take == -1) { will_get[n] = -1; } else { proposal[n] = my_take; swap(will_get, proposal); } debug(n, my_take, will_get); } REP (i, N) cout << will_get[i] << " "; cout << "\n"; return 0; } |
English