Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Throwing flip flops at a monster is only useful if that monster eventually dies. Otherwise you are literally spending resources to make your problem worse. Classic gamer move, but not optimal.
Suppose you decide to kill a monster with right now. Ask: should you throw fewer flip flops than possible, or as many as you can while still keeping ?
Let . If you kill monster and throw optimally first, then The value becomes .
For the same current state, a larger killable gives a larger or equal next state: both and improve. Small killable monsters stay killable later, so there is no rush to take them first.
Greedy it is: repeatedly take the alive monster with maximum , throw flip flops at it, then kill it. If no monster satisfies , stop. That's the whole damn trick.
If a monster is never killed, throwing flip flops at it is useless: it consumes flip flop and increases that monster's power by , making it harder to kill. So every useful flip flop must be thrown at a monster that will eventually die.
Now suppose the current combat power is , we have flip flops left, and we decide to kill a monster with initial power right now.
Before killing it, we may throw flip flops at it, but it must remain killable:
Also . Therefore the maximum legal choice is
Using fewer is never better. One extra flip flop used now decreases by but increases the resulting by . The total resource stays the same, while current combat power gets larger. Larger current power can only help. So if we kill a monster now, we should pump it as much as possible before killing it.
Let
After killing a chosen monster with the maximum possible number of flip flops,
because killing adds the monster's original power , and thrown flip flops merely move value from into .
The new combat power is
Since , this becomes
This formula is the whole problem wearing a fake mustache.
Among all currently killable monsters, choose the one with maximum .
Why? For fixed current , killing a larger gives a larger
and therefore also a larger or equal
So the strongest killable monster gives the best next state. Smaller killable monsters are not going anywhere: since never decreases, if now, then it will remain killable later.
A clean exchange argument seals it. Suppose an optimal strategy first kills some killable monster , but there is another killable monster with . Kill first instead. The resulting state dominates the original one: it has at least as much current combat power and at least as much total resource . Then follow the old strategy; when it would have killed , kill instead. Since was killable from the start, it is still killable. The strategy is no worse. So taking the largest killable monster is safe.
Repeat:
There are only monsters, so a simple linear scan each step is more than enough.
For each test case, we do at most iterations, and each iteration scans monsters.
time and
memory. Use 64-bit integers: the answer can exceed , as the sample politely screams at you.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll c, k;
cin >> n >> c >> k;
vector<ll> a(n);
for (ll &x : a) cin >> x;
vector<bool> dead(n, false);
for (int step = 0; step < n; step++) {
int id = -1;
for (int i = 0; i < n; i++) {
if (!dead[i] && a[i] <= c && (id == -1 || a[i] > a[id])) {
id = i;
}
}
if (id == -1) break;
ll use = min(k, c - a[id]);
k -= use;
c += a[id] + use;
dead[id] = true;
}
cout << c << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll c, k;
cin >> n >> c >> k;
vector<ll> a(n);
for (ll &x : a) cin >> x;
vector<bool> dead(n, false);
for (int step = 0; step < n; step++) {
int id = -1;
for (int i = 0; i < n; i++) {
if (!dead[i] && a[i] <= c && (id == -1 || a[i] > a[id])) {
id = i;
}
}
if (id == -1) break;
ll use = min(k, c - a[id]);
k -= use;
c += a[id] + use;
dead[id] = true;
}
cout << c << '\n';
}
return 0;
}