码迷,mamicode.com
首页 > 其他好文 > 详细

[CF713C] Sonya and Problem Wihtout a Legend - dp

时间:2021-02-16 11:54:21      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:相同   cout   names   操作   lse   const   次数   ace   转化   

[CF713C] Sonya and Problem Wihtout a Legend - dp

Description

给定一个数组,每次操作可以把任意一个元素 +1 或者 -1。求使得递增的最小操作次数。 n<=3000

Solution

首先通过 ai=ai-i,转化为单调不降

最终的序列中,一定由若干连续相同的段构成,并且不会出现原序列未出现的数

考虑离散化,设 \(val[i]\) 表示离散化后第 i 个数,设 \(f[i][j]\) 表示将前 i 个数修改成不降,且最后一个数与 \(val[j]\) 相同,需要的代价

前缀最小值维护一下即可

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

#define int long long
const int N = 3005;

int f[N][N], n, a[N], val[N];

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

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

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

    int ind = 0;
    for (auto &[x, y] : mp)
        y = ++ind, val[ind] = x;

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

    for (int i = 1; i <= n; i++)
    {
        int mn = 1e18;
        for (int j = 1; j <= ind; j++)
        {
            mn = min(mn, f[i - 1][j]);
            f[i][j] = mn + abs(val[a[i]] - val[j]);
        }
    }

    cout << *min_element(f[n] + 1, f[n] + ind + 1) << endl;
}

[CF713C] Sonya and Problem Wihtout a Legend - dp

标签:相同   cout   names   操作   lse   const   次数   ace   转化   

原文地址:https://www.cnblogs.com/mollnn/p/14398608.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!