題解:AT_arc174_a [ARC174A] A Multiply

lucky_cloud發表於2024-03-23

題傳

先要將 \(C\) 分類。

  1. \(C > 0\),為了使答案更大,要乘上一個最大的區間和。
  2. \(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;
}

相關文章