Maintain an entire convex piecewise-linear function in a pair of heaps, supporting the operations a DP needs in each. It turns a DP whose state is a function into one whose state is a data structure.
The representation
A convex piecewise-linear is determined by:
- its minimum value ,
- the multiset of slope-change points to the left of the minimum (kept in a max-heap ),
- the multiset of slope-change points to the right (kept in a min-heap ).
Each breakpoint appears once per unit of slope change. Convexity guarantees .
The operations
| Operation | Implementation | Cost |
|---|---|---|
push to both heaps, then rebalance; minf += max(0, L.top() - R.top()) | ||
| push to only (with a rebalance) | ||
| push to only (with a rebalance) | ||
minf += c | ||
| shift: | lazy offsets on both heaps | |
| prefix min: | clear | |
| suffix min: | clear | |
| sliding min: | shift by , shift by | |
| query the minimum | minf | |
| query at a point | sum the contributions — , rarely needed |
Adding , concretely
priority_queue<long long> L; // max-heap
priority_queue<long long, vector<long long>, greater<>> R; // min-heap
long long addL = 0, addR = 0, minf = 0;
void addAbs(long long a) {
L.push(a - addL);
R.push(a - addR);
long long l = L.top() + addL, r = R.top() + addR;
if (l > r) { // fix the ordering
L.pop(); R.pop();
L.push(r - addL); R.push(l - addR);
minf += l - r;
}
}The minf += l - r line is the only place the minimum value changes, and it is exactly the amount by which the two pushed breakpoints were out of order.
The canonical problem
“Given , make the sequence non-decreasing with the minimum total .”
Define = minimum cost for the first elements with . Then
Each step is one “clear ” plus one “add ”. Total , and the answer is the final minf.
long long minCostNonDecreasing(vector<long long>& a) {
priority_queue<long long> L;
long long ans = 0;
for (long long x : a) {
L.push(x);
if (L.top() > x) { ans += L.top() - x; L.pop(); L.push(x); }
}
return ans;
}Eight lines, and it is one of the most striking algorithms in competitive programming — the heap disappears entirely because the prefix-min clears it every step.
For strictly increasing, subtract from each first; the problem becomes non-decreasing.
When it applies
| Signal | |
|---|---|
| The DP value as a function of one parameter is convex | required |
| Transitions add , , or constants | ✔ |
| Transitions take prefix/suffix minima or shift the function | ✔ |
| You only need the final minimum, not the whole function | ✔ |
| The function is not convex | ✘ — slope trick is invalid |
Convexity is preserved by all the operations above, which is why the representation stays valid throughout.
Related techniques
| Technique | State is |
|---|---|
| Slope trick | a convex piecewise-linear function, in heaps |
| CHT | a set of lines, lower envelope |
| Li Chao tree | a set of lines, in a segment tree |
| Aliens trick | a convex sequence indexed by a group count |
| ”Segment tree beats” on a convex function | a function with range updates |
All four exploit convexity; slope trick is the one that keeps the entire function around.
See also: Convex Hull Trick · Aliens Trick · Binary Heap