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.
Think of every attack that kills some mob as a cut in a current stack. The lower part survives as its own stack, while the upper part may get some free damage from falling. The game is really about choosing where to make those cuts.
If a mob dies because the mob right below it died inside the same falling stack, it only gets fall damage. The only “large” fall damage happens to the mob immediately above the mob Steve directly killed: it takes the number of mobs below it in that current stack.
A very useful normal form: mobs can be finished from top to bottom inside a segment, except sometimes you first kill a lower mob to give a big fall hit to the next mob. Once a stack is split, the two parts never interact again, so prefixes matter.
Let be the minimum attacks needed to kill mobs completely. If mob is just killed normally after everything below is handled, that costs , giving .
The nontrivial transition is to kill mob first, so mob falls from height and needs only extra attacks. But mob itself can get fall damage from mob dying, so its effective cost is . This gives a 1D DP with a two-mob transition.
The problem looks like a chaotic pile of mobs, but the key is that stacks split, and after splitting, they never merge again. So we should stop trying to simulate Minecraft physics like a sleep-deprived YouTuber and instead ask: what local benefit can one death give to the mob above it?
What fall damage can actually do
Suppose Steve directly kills some mob at position in its current stack, counting from the bottom of that stack.
Then the mob immediately above it takes fall damage. If that mob dies too, the next mob above takes only fall damage, because now it was only above one mob in the newly formed falling stack.
So there are two kinds of useful free damage:
That sounds more complicated than it is. The huge observation is that the big hit can only help one adjacent pair: kill lower mob, damage the one right above it. Everything else in the cascade gets at most damage, which can be handled locally.
DP definition
Let be the minimum number of attacks needed to kill the first mobs, i.e. mobs .
We process from bottom to top.
Base cases:
For one mob, Steve just kills it:
Now consider how mob dies.
Option 1: kill mob normally
Maybe nothing fancy happens with mob . We first kill mobs optimally, then spend attacks on mob .
That gives:
This transition is boring, but boring is often AC. Sadly, not always.
Option 2: use mob to drop mob
The useful trick is to directly kill mob while mob is still above it. Then mob takes fall damage equal to the number of mobs below it in that current stack.
When we are considering the prefix , that fall damage can be treated as . So after mob dies, mob still needs:
attacks.
What about mob itself? It may receive fall damage when mob dies. That means killing mob costs not , but effectively:
Why the ? Because Steve still needs some attack to make mob be the directly killed mob that causes mob to fall. If it already had health after fall damage, one attack kills it. If the fall damage would have killed it automatically, then it would not be Steve's chosen cut anymore, so this transition must still pay one attack for that role. Tiny detail, massive wrong-answer trap. Classic Codeforces nonsense.
The mobs below are handled optimally as .
So the pair transition is:
Full recurrence
For every :
The answer is .
Why this is enough
Any useful large fall damage is caused by killing the mob directly below the damaged mob. That means the only special interaction involving mob is with mob .
If mob does not use that interaction, it is just paid for normally after the prefix below is gone.
If it does use that interaction, then mob must be the cut mob, and everything below is independent, already represented by . The possible fall damage into mob is exactly why the cost uses .
So the recurrence covers all optimal endings for the prefix. No hidden mega-combo is missing; the physics only lets the big damage cross one edge.
Complexity
Each mob is processed once.
per test case, and
over all test cases. Use long long, because health can be and there can be mobs. Ints will faceplant.
#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;
cin >> n;
vector<ll> h(n + 1);
for (int i = 1; i <= n; i++) cin >> h[i];
vector<ll> dp(n + 1, 0);
dp[0] = 0;
dp[1] = h[1];
for (int i = 2; i <= n; i++) {
ll normal = dp[i - 1] + h[i];
ll drop = dp[i - 2]
+ max(1LL, h[i - 1] - 1)
+ max(0LL, h[i] - (ll)(i - 1));
dp[i] = min(normal, drop);
}
cout << dp[n] << '\n';
}
}#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;
cin >> n;
vector<ll> h(n + 1);
for (int i = 1; i <= n; i++) cin >> h[i];
vector<ll> dp(n + 1, 0);
dp[0] = 0;
dp[1] = h[1];
for (int i = 2; i <= n; i++) {
ll normal = dp[i - 1] + h[i];
ll drop = dp[i - 2]
+ max(1LL, h[i - 1] - 1)
+ max(0LL, h[i] - (ll)(i - 1));
dp[i] = min(normal, drop);
}
cout << dp[n] << '\n';
}
}