[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;
}