題傳。
先要將 \(C\) 分類。
- \(C > 0\),為了使答案更大,要乘上一個最大的區間和。
- \(C \le 0\),為了使答案更大,選擇乘上一個最小的區間和,因為此時我們可以貪心地想,如果區間和越小,乘上一個負數或 \(0\) 後,答案減少得越小,甚至乘上負數,還會使答案增大,所以也可以用負負得正來解釋。
當然我們也可以不進行操作。
要求區間和,我們選擇字首和即可。
因為字首和求區間 \(l \sim r\) 的和是 \(sum_r - sum_{l - 1}\)。要求區間和的最值,我們固定 \(sum_r\) 就可以求 \(sum_{l - 1}\) 的最值,我們遍歷一遍並動態維護一下區間和的最值即可。
注意 \(i \sim i + 1\) 我們可以視為不選區間與 \(C\) 相乘。
給一下程式碼:
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read() {
int res = 0, f = 1; char c = getchar();
while (c > '9' || c < '0') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
res = (res << 1) + (res << 3) + (c ^ 48);
c = getchar();
}
return f == 1 ? res : -res;
}
int n, c, a[(int)3e5 + 5], sum[(int)3e5 + 5];
signed main() {
n = read(), c = read();
for (int i = 1; i <= n; ++i)
a[i] = read(), sum[i] = sum[i - 1] + a[i];
if (c > 0) {
int ans = -1e18, mi = 0;
for (int i = 1; i <= n; ++i) {
mi = min(sum[i], mi);//求 sum[i-1] 的最值,下同。
ans = max(ans, sum[i] - mi);//求和的最值,下同。
}
cout << sum[n] - ans + c * ans;//計算答案下同。
}
else {
int ans = 1e18, mx = 0;
for (int i = 1; i <= n; ++i) {
mx = max(sum[i], mx);
ans = min(ans, sum[i] - mx);
}
cout << sum[n] - ans + c * ans;
}
return 0;
}