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 operation’s effect on a range is just a gain over the original sum. If the original total is , then for range the new total is .
For a fixed range , the gain is
So the whole problem is: find the maximum value of that expression, or use if every operation is bad.
The sneaky part is simplifying the weird-looking range value:
That identity is basically the problem handing you the answer while wearing fake glasses.
Use prefix sums . Then the gain becomes
Now the right endpoint and left endpoint are separated.
Scan from left to right. Maintain the minimum value of
among all valid . Then the best range ending at is immediate.
Let the original array sum be . If we choose a range , every element in it becomes , so the new sum is
So we only need to maximize the gain:
Since the operation is optional, the final answer is
The key algebra trick
The expression looks annoying, but it collapses cleanly:
You can verify it by expanding both sides:
And
Same thing. Very convenient. Suspiciously convenient, even.
Now define prefix sums:
with . Then
Plug that into the gain:
Rearrange:
Now the expression splits into:
That means for each fixed right endpoint , the best left endpoint is simply the one minimizing
among all .
Algorithm
Scan from to .
Before evaluating endpoint , make sure the candidate left endpoint is available. Its value is
Maintain
Then the best gain for ranges ending at is
Track the maximum gain over all .
Finally print:
Why this is correct
Every possible operation corresponds to exactly one pair with . For that pair, the gain formula above is exact.
For a fixed , the term is fixed. So maximizing the gain is equivalent to minimizing
over all valid .
The scan maintains exactly that minimum before computing the answer for each . Therefore, for every right endpoint, we consider the best possible left endpoint. Taking the maximum over all considers every range. Since we also compare against doing nothing with gain , the optional operation is handled too.
Complexity
Each test case is processed in one pass.
Time complexity:
Memory complexity: if storing prefix sums, or extra with a running prefix. The implementation below uses the simple running-prefix version.
#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;
ll pref = 0;
ll bestLeft = LLONG_MAX;
ll bestGain = 0;
for (int i = 1; i <= n; i++) {
ll x;
cin >> x;
bestLeft = min(bestLeft, 1LL * i * (i - 1) - pref);
pref += x;
ll rightPart = 1LL * i * (i + 1) - pref;
bestGain = max(bestGain, rightPart - bestLeft);
}
cout << pref + bestGain << '\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;
cin >> n;
ll pref = 0;
ll bestLeft = LLONG_MAX;
ll bestGain = 0;
for (int i = 1; i <= n; i++) {
ll x;
cin >> x;
bestLeft = min(bestLeft, 1LL * i * (i - 1) - pref);
pref += x;
ll rightPart = 1LL * i * (i + 1) - pref;
bestGain = max(bestGain, rightPart - bestLeft);
}
cout << pref + bestGain << '\n';
}
return 0;
}