这两个题是一样的,不过数据范围不同。
思路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; }