Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Stop thinking about individual moves. If the final sequence is , then the number of moves is just . So the real problem is choosing a good non-decreasing sequence .
You do not need to try every integer as a target value. Between two consecutive values from the original array, the cost behaves linearly, so an optimum can be pushed to an endpoint.
Sort the original values and use them as candidate targets. If the -th final value is the -th candidate, what can the -th final value be?
Let be the minimum cost to fix the first numbers if the -th final number equals candidate . Then That is exactly the non-decreasing constraint.
Compute each DP row left-to-right. Maintain Then so each row is and the whole DP is . Two rows of memory are enough.
Forget the literal operations. They are just a dramatic way to say this:
choose integers such that and minimize
So this is an isotonic regression problem. Sounds fancy. The solution is just a clean DP once you stop the problem from cosplaying as a simulation.
Let be the set of distinct values appearing in the original array. We claim there exists an optimal answer where every belongs to .
Why? Take any optimal non-decreasing sequence , and suppose some value appears. Look at one maximal block Let To keep the sequence non-decreasing, we may replace the whole block by any value with .
Now let be consecutive values in around . Since no original value lies inside , the block cost is linear on . Therefore on the feasible interval it reaches its minimum at an endpoint.
That endpoint is either:
In both cases we do not increase the cost, and we reduce the number of weird target values not from . Repeat this until all chosen values are from .
So we only need to consider candidate target values from the sorted original array. You can keep duplicates or remove them; both work. I will use the distinct sorted values .
Define
If , then because must be non-decreasing, the previous value must be some with . Therefore
That is the whole problem. No black magic, just one honest transition.
Naively, the transition is per state, which would be and kind of gross.
But for fixed , the needed value is just a prefix minimum: Then
So each DP row can be computed in one left-to-right pass.
We can initialize for all , meaning before processing any elements, the cost is zero regardless of the last chosen candidate. After processing all elements, the answer is
Let be the number of distinct values in the array. Then:
With , this passes comfortably.
long long. The answer can be around , which absolutely does not fit in int.That is it. Once you rephrase the cost correctly, the problem stops being scary and becomes a very standard monotone DP.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int n;
if (!(cin >> n)) return 0;
vector<ll> a(n), vals;
vals.reserve(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
vals.push_back(a[i]);
}
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
int m = (int)vals.size();
vector<ll> prev(m, 0), cur(m);
for (int i = 0; i < n; ++i) {
ll best = (1LL << 62);
for (int j = 0; j < m; ++j) {
best = min(best, prev[j]);
cur[j] = best + abs(a[i] - vals[j]);
}
swap(prev, cur);
}
cout << *min_element(prev.begin(), prev.end()) << '\n';
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int n;
if (!(cin >> n)) return 0;
vector<ll> a(n), vals;
vals.reserve(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
vals.push_back(a[i]);
}
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
int m = (int)vals.size();
vector<ll> prev(m, 0), cur(m);
for (int i = 0; i < n; ++i) {
ll best = (1LL << 62);
for (int j = 0; j < m; ++j) {
best = min(best, prev[j]);
cur[j] = best + abs(a[i] - vals[j]);
}
swap(prev, cur);
}
cout << *min_element(prev.begin(), prev.end()) << '\n';
}