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.
The swap only changes the order inside one magazine. The total damage of a full magazine, , never changes.
If the enemy dies on bullet of some magazine, the time looks like
where full magazines were already fired before this one.
So for each prefix length , you only care about the maximum possible damage in the first bullets after at most one swap.
A prefix of length can be improved only by swapping one bullet inside the prefix with one bullet outside it. That means:
if that helps; otherwise keep .
For every , compute how many full magazines are still needed before that final prefix:
Then minimize . No binary search needed; the math bonks the problem on the head.
Let . A full magazine always deals damage, no matter how we swap bullets, because swapping changes order, not total damage.
Now suppose the killing shot is the -th bullet of some magazine, where . Before that magazine, we have already fired complete magazines. The total damage is
where is the damage in the first bullets of the swapped magazine. The time is
because each completed magazine costs shooting seconds plus reload seconds, and then we shoot bullets in the final magazine.
So the whole problem becomes: for every , what is the maximum possible prefix sum of length after at most one swap?
Let
For a fixed prefix length , a useful swap must move some bullet from outside the prefix into the prefix. Swapping two bullets both inside the prefix changes nothing about the prefix sum. Swapping two bullets both outside changes nothing. Swapping a prefix bullet with a suffix bullet changes the prefix sum by
where and .
To maximize this gain, remove the smallest bullet currently inside the prefix and bring in the largest bullet outside the prefix. Therefore
where and .
For , there is no outside bullet, so no swap can improve the full-magazine prefix. In that case .
Once we know , the least number of complete magazines needed before the final prefix is:
0, & \text{if } \text{best}[r]\ge h,\\ \left\lceil\dfrac{h-\text{best}[r]}{S}\right\rceil, & \text{otherwise.} \end{cases}$$ Then this candidate answer is $$q(n+k)+r.$$ We take the minimum over all $r$. Why this is enough: every valid fight ends at some prefix length $r$ of a magazine after some number $q$ of complete magazines. Since the complete magazines always contribute exactly $qS$, only the final prefix can be optimized. For that final prefix, the best single swap is exactly replacing its minimum element with the maximum element outside it if profitable. There is no secret extra move hiding under the couch. Edge cases: - If the enemy dies in the first magazine, the formula naturally gives $q=0$. - If $r=n$, the final prefix is the whole magazine, so swapping is irrelevant. - Very large health needs 64-bit integers: time and damage can go far beyond `int`. Complexity is $O(n)$ per test case, with $O(n)$ memory. Since the sum of $n$ over all tests is at most $2\cdot 10^5$, this easily fits.#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 h, k;
cin >> n >> h >> k;
vector<ll> a(n + 2), pref(n + 1), prefMin(n + 1), sufMax(n + 2, 0);
ll sum = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
pref[i] = pref[i - 1] + a[i];
prefMin[i] = (i == 1 ? a[i] : min(prefMin[i - 1], a[i]));
}
for (int i = n; i >= 1; i--) {
sufMax[i] = max(sufMax[i + 1], a[i]);
}
ll ans = LLONG_MAX;
for (int r = 1; r <= n; r++) {
ll best = pref[r];
if (r < n) {
best += max(0LL, sufMax[r + 1] - prefMin[r]);
}
ll full = 0;
if (best < h) {
full = (h - best + sum - 1) / sum;
}
ans = min(ans, full * (n + k) + r);
}
cout << ans << '\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;
ll h, k;
cin >> n >> h >> k;
vector<ll> a(n + 2), pref(n + 1), prefMin(n + 1), sufMax(n + 2, 0);
ll sum = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
pref[i] = pref[i - 1] + a[i];
prefMin[i] = (i == 1 ? a[i] : min(prefMin[i - 1], a[i]));
}
for (int i = n; i >= 1; i--) {
sufMax[i] = max(sufMax[i + 1], a[i]);
}
ll ans = LLONG_MAX;
for (int r = 1; r <= n; r++) {
ll best = pref[r];
if (r < n) {
best += max(0LL, sufMax[r + 1] - prefMin[r]);
}
ll full = 0;
if (best < h) {
full = (h - best + sum - 1) / sum;
}
ans = min(ans, full * (n + k) + r);
}
cout << ans << '\n';
}
}