abc 263 d 题解
abc 263 d
题意
给定一个长度为 \(N\) 的序列 \(A\)。有两种操作,各做一次:
-
选择一个整数 \(x \ (0 \le x \le N)\),将 \(A_1, A_2, \dots , A_x\) 替换为 \(L\)。
-
选择一个整数 \(y \ (0 \le y \le N)\),将 \(A_N, A_{N - 1}, \dots , A_{N - y + 1}\) 替换成 \(R\)。
请你求出操作后的 \(A\) 序列的最小数字和。
思路
首先,我们可以想到:我们选择改变的两个前缀和后缀是不会重叠的。
因为如果重叠了,就会有一个覆盖另一个,完全没有必要。
那么,我们可以把答案分成两段,\(1 \sim i\) 和 \(i + 1 \sim N\)。
我们就可以分别求出 \(1 \sim i\) 的最小数字和,把它记作 \(g_i\)。
那么就有 \(g_i = \min(g_{i - 1} + A_i, i \times L)\),\(g_{i - 1} + A_i\) 是不变为 \(L\) 的情况,\(i \times L\) 是前 \(i\) 个全变成 \(L\) 的情况。
同理,我们将 \(i \sim N\) 的最小数字和记作 \(f_i\)。
那么就有 \(f_i = \min(f_{i + 1} + A_i, (N - i + 1) \times R)\)。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, l, r, a[N];
long long g[N], f[N], ans = 1e18;
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> l >> r;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
g[i] = min(g[i - 1] + a[i], 1ll * i * l);
}
for (int i = n; i >= 1; i--) {
f[i] = min(f[i + 1] + a[i], 1ll * (n - i + 1) * r);
}
for (int i = 0; i <= n; i++) {
ans = min(ans, g[i] + f[i + 1]);
}
cout << ans;
return 0;
}