CF713C Sonya and Problem Wihtout a Legend & hihocoder1942 单调序列

这两个题是一样的,不过数据范围不同。

思路1:

在CF713C中,首先考虑使生成序列单调不下降的情况如何求解。因为单调上升的情况可以通过预处理将a[i]减去i转化成单调不下降的情况。

首先,生成的序列中的每个数一定是原序列中的数。于是可以通过dp+离散化技巧解决。dp[i][j]表示把前i个数变成单调不下降的序列,并且a[i]不超过第j大的数所需要的最小代价。

实现1:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int N = 3005;
 5 ll a[N], dp[N][N];
 6 int main()
 7 {
 8     int n;
 9     while (cin >> n)
10     {
11         for (int i = 1; i <= n; i++) { cin >> a[i]; a[i] -= i; }
12         vector<ll> v(a + 1, a + n + 1);
13         sort(v.begin(), v.end());
14         v.erase(unique(v.begin(), v.end()), v.end());
15         int m = v.size();
16         for (int i = 1; i <= n; i++)
17         {
18             for (int j = 0; j < m; j++)
19             {
20                 dp[i][j] = dp[i - 1][j] + abs(a[i] - v[j]);
21                 if (j) dp[i][j] = min(dp[i][j], dp[i][j - 1]);
22             }
23         }
24         cout << dp[n][m - 1] << endl;
25     }
26     return 0;
27 }

思路2:

n2的复杂度不足以解决hihocoder1942,因此需要进行优化。下面这种数形结合的斜率优化思路参考了

https://codeforces.com/blog/entry/47094?#comment-315161

以下的代码是针对hihocoder1942的实现:

实现2:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005;
int a[N];
ll solve(int n)
{
    ll ans = 0;
    priority_queue<int> pq;
    for (int i = 1; i <= n; i++)
    {
        pq.push(a[i]);
        if (a[i] < pq.top())
        {
            ans += (ll)pq.top() - a[i];
            pq.pop();
            pq.push(a[i]);
        }
    }
    return ans;
}
int main()
{
    int n, x;
    while (cin >> n)
    {
        for (int i = 1; i <= n; i++) cin >> a[i];
        ll ans = solve(n);
        reverse(a + 1, a + n + 1);
        ans = min(ans, solve(n));
        cout << ans << endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/wangyiming/p/10833039.html

时间: 2024-08-04 01:14:43

CF713C Sonya and Problem Wihtout a Legend & hihocoder1942 单调序列的相关文章

CF713C Sonya and Problem Wihtout a Legend (经典dp)

一个经典的通过增长减小大小来求使得序列单调性的最小代价. 对于这道题,有一个前置题是不要求要严格单调,而是不严格单调 这样的话,我们可以得到一个性质,最后所有的值都是在原序列当中的,这其实用贪心的想法想一想就好,因为一旦通过加减与左边或右边相等,就没必要再加减了 但是本题要求严格,这就很难说了,因此要考虑将一个问题转化成已知的问题 对于原先的问题,其实就是a[i]-a[j]>=0就好 那么现在的问题是a[i]-a[j]>=i-j,因此我们只要对输入的原数列减下标i,就转化成上面的问题了 也就是

Codeforces 713C Sonya and Problem Wihtout a Legend(单调DP)

[题目链接] http://codeforces.com/problemset/problem/713/C [题目大意] 给出一个数列,请你经过调整使得其成为严格单调递增的数列,调整就是给某些位置加上或者减去某个数,调整的代价是加上或者减去的数的绝对值之和,请你输出最小代价. [题解] 先考虑这样一个问题,如果是非严格单调递增该如何做,我们会发现每次调整,都是调整某个数字为原先数列中存在的数字,最后才是最优的,所以,我们设DP[i][j]表示前i个数字,最后一个数为原先数列排序后第j大的数字的最

把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend

1 //把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend 2 //dp[i][j]:把第i个数转成第j小的数,最小花费 3 //此题与poj 3666相似 a[i]转换成a[i]-i 4 5 #include <iostream> 6 #include <cstdio> 7 #include <cstdlib> 8 #include <algorithm> 9 #include <

Codeforces713C Sonya and Problem Wihtout a Legend(DP)

题目 Source http://codeforces.com/problemset/problem/713/C Description Sonya was unable to think of a story for this problem, so here comes the formal description. You are given the array containing n positive integers. At one turn you can pick any ele

Sonya and Problem Wihtout a Legend

Sonya was unable to think of a story for this problem, so here comes the formal description. You are given the array containing n positive integers. At one turn you can pick any element and increase or decrease it by 1. The goal is the make the array

CF 713C Sonya and Problem Wihtout a Legend(DP)

原版题意:给定一个序列,每次操作给其中一个数$+1$或$-1$,问最少需要多少操作使得整个序列为不下降序列. 题解:不下降序列最后修改完成后的各个数一定是原序列中的某一个数.关于这个的理解看到网上的一个解释:原序列,从左到右扫过去,如果左边的大于右边的,要么左边的减掉使其等于右边的,要么右边的加上使其等于左边的. $dp[i][j]$:前i个数以原序列排序后的第j个数为结尾需要的最少操作. 状态转移方程:$dp[i][j]=min(dp[i][j-1],dp[i-1][j]+abs(a[i]-b

CodeForces 713C Sonya and Problem Wihtout a Legend

$dp$. 非严格递增的可以由$dp$解决.可以将严格递增转化为非严格递增. 要保证$a[i]<a[i+1]$,就是要保证$a[i]<=a[i+1]-1$,也就是$a[i]-i≤a[i+1]-1-i$,等价于$a[i]-i≤a[i+1]-(i+1)$. 因此只要将$a[i]-i$,求非严格递增的就可以了. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #inclu

HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 5943    Accepted Submission(s): 2004 Problem Description Before

HDU 6319 Problem A. Ascending Rating(单调队列)

要求一个区间内的最大值和每次数过去最大值更新的次数,然后求每次的这个值异或 i 的总和. 这个序列一共有n个数,前k个直接给出来,从k+1到n个数用公式计算出来. 因为要最大值,所以就要用到单调队列,然后从后往前扫一遍然后每次维护递减的单调队列. 先把从n-m+1以后开始的数放进单调队列,这时候先不操作,然后剩下的数就是要异或相加的数,然后每次的队首元素就是这个区间内的最大值,这个队列里的元素个数,其实就是更新到最大值的逆过程,也就是最大值需要更新的次数. #include<map> #inc