[CF13C] Sequence - dp

[CF13C] Sequence - dp

Description

给定一个序列,每次操作可以把某个数 +1,-1。要求把序列变成非降数列。而且要求修改后的数列只能出现修改前的数。

Solution

设 \(f[i][j]\) 表示处理了前 i 个数,当前最大数不超过离散化后的 j 的最小代价

转移的时候,对于状态 (i,j) 最后一个数一定变成了 j,因此这里提供的代价就是 abs(ai-cj)

于是 \(f[i][j]= min(f[i][j-1], f[i-1][j]+abs(ai-cj))\)

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 5005;

signed main()
{
    ios::sync_with_stdio(false);

    int n;
    cin >> n;

    vector<int> a(n + 2);
    for (int i = 1; i <= n; i++)
        cin >> a[i];

    map<int, int> mp;
    for (int i = 1; i <= n; i++)
        mp[a[i]]++;

    int ind = 0;
    vector<int> c(n + 2);
    for (auto &[x, y] : mp)
        y = ++ind, c[ind] = x;
    for (int i = 1; i <= n; i++)
        a[i] = mp[a[i]];

    vector<vector<int>> f(2, vector<int>(n + 2, 1e18));

    for (int i = 1; i <= ind; i++)
        f[0][i] = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= ind; j++)
        {
            f[i & 1][j] = min(f[i & 1][j - 1], f[(i & 1) ^ 1][j] + abs(c[a[i]] - c[j]));
        }
    }

    cout << f[n & 1][ind] << endl;
}
上一篇:【leetcode】695. 岛屿的最大面积


下一篇:[CF1468M] Similar Sets - 根号分治