Loading

abc 263 d 题解

abc 263 d

题意

给定一个长度为 \(N\) 的序列 \(A\)。有两种操作,各做一次:

  1. 选择一个整数 \(x \ (0 \le x \le N)\),将 \(A_1, A_2, \dots , A_x\) 替换为 \(L\)

  2. 选择一个整数 \(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;
}
posted @ 2023-05-17 14:58  chengning0909  阅读(5)  评论(0编辑  收藏  举报