嘘~ 正在从服务器偷取页面 . . .

CF1969C Minimizing the Sum 题解


CF1969C Minimizing the Sum 题解

题目链接:Minimizing the Sum

题意

给你一个长度为 \(n(1 \le n \le 3 \times 10^5)\) 的整数数组 \(a(1 \le a_i \le 10^9)\)

你可以执行以下操作:选择数组中的一个元素,并用其邻近元素的值替换它。

你的任务是计算在执行上述操作最多 \(k(0 \le k \le 10)\) 次的情况下,数组的总和可能达到的最小值。

注意到 \(k\) 十分的小,我们可以直接dp

\(f_{i,j}\) 表示前 \(i\) 个数修改 \(j\) 次的最小值。转移就钦定 \([l+1,~i]\)​ 全部推成最小值。

时间复杂度 \(\mathcal{O}(nk^2)\)

代码:(考场上光速写的,可能不够优雅

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(3e5 + 15))

int n, a[N], f[N][12];
void solve()
{
    int k, s = 0; cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 0; i <= n; i++)
        for(int t = 0; t <= k; t++) f[i][t] = INF;
    f[0][0] = 0;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= k; j++)
        {
            down(f[i][j], f[i - 1][j] + a[i]);
            int mn = a[i];
            for(int l = 1; j - l + 1 >= 0 && i - l >= 0; l++)
            {
                down(mn, a[i - l + 1]);
                down(f[i][j], f[i - l][j - l + 1] + mn * l);
            }
        }
    }
    int res = INF;
    for(int i = 0; i <= k; i++) down(res, f[n][i]);
    cout << res << '\n';
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int qwq; cin >> qwq; while(qwq--) solve();
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录