Slope Trick Optimization

Introduction

For a class of two-dimensional DP problems, if its value function f(i,x)f(i,x), for every fixed ii, is a convex function of xx, then treating the entire function f(i,⋅)f(i,\cdot) as the state at ii and maintaining its difference (or slope)

Δf(i,x)=f(i,x+1)−f(i,x)\Delta f(i,x) = f(i,x+1)-f(i,x)

rather than the function itself often helps optimize the transitions. This idea of optimizing DP is called Slope Trick.

Slope

Because the functions in most problems take values only at integer points, there is no essential difference between calling this quantity a difference or a slope. This article consistently calls it a slope, following the term Slope Trick.

The way slopes are maintained may vary from problem to problem. If the range of slope values is narrow, it is more convenient to maintain the points where the slope changes, namely the kinks. If the domain of the function is narrow, it may be more convenient to maintain the slope sequence itself. In more complicated cases, it may be necessary to maintain both the size of each slope and the length of its segment. Regardless of the particular maintenance method, the essence of these problems is to simplify transitions by exploiting the fact that the slope sequence changes only slightly during a state transition. Therefore, all of them can be called Slope Trick.

Convex Functions

Before discussing specific problems, it is useful to understand the basic properties of convex functions and how their slopes change under various transformations.

Convex Functions on the Real Line

The more general definition of a convex function is given on R\mathbf R.

Figure: epigraph convex def
Convex Function on R\mathbf R

A function f:R→R∪{±∞}f:\mathbf R\rightarrow\mathbf R\cup\{\pm\infty\} is called a convex function if, for every x,y∈Rx,y\in\mathbf R and α∈(0,1)\alpha\in(0,1), it satisfies

f(αx+(1−α)y)≤αf(x)+(1−α)f(y),f(\alpha x+(1-\alpha)y) \le \alpha f(x)+(1-\alpha)f(y),

We call ff a convex function, where the arithmetic rules for ±∞\pm\infty specify that multiplying ±∞\pm\infty by any positive real number, or adding any real number to it, gives itself, and that for every real x∈Rx\in\mathbf R, −∞<x<+∞-\infty<x<+\infty.

If the inequality is replaced by ≥\ge, the function is correspondingly called concave1. Since ff is concave, −f-f is convex, so this section considers only convex functions.

Only Proper Convex Functions Are Considered

To avoid discussing the value of ∞−∞\infty-\infty and additional technical complications, whenever concepts related to convex functions are discussed, we assume that the function never takes the value −∞-\infty and is not identically +∞+\infty. Such a function is called a proper convex function. This is sufficient for understanding the algorithmic content of programming competitions.

In general, a function ff need not be defined for every real number. If the domain of ff is only a subset of R\mathbf R, extend it to a function on R\mathbf R as follows:

f~(x)={f(x),x∈dom⁡f,+∞,x∉dom⁡f.\tilde f(x) = \begin{cases} f(x), & x\in\operatorname{dom}f,\\ +\infty,& x\notin\operatorname{dom}f.\end{cases}

Then ff is called convex if and only if the corresponding f~\tilde f satisfies the definition above. Thus, unless stated otherwise, the domain of every convex function mentioned in this article is the real line R\mathbf R. Clearly, a convex function ff can take finite values only on an interval, that is, a convex subset of R\mathbf R.

Simple Examples

Common examples of convex functions include:

  1. A constant function: f(x)=cf(x)=c, where c∈Rc\in\mathbf R;
  2. A linear function: f(x)=kx+bf(x)=kx+b, where k,b∈Rk,b\in\mathbf R and k≠0k\neq 0;
  3. The absolute-value function: f(x)=∣x−a∣f(x)=|x-a|, where a∈Ra\in\mathbf R;
  4. The restriction of any convex function to an interval, such as 0[a,b](x)0_{[a,b]}(x) (also called the indicator function of [a,b][a,b] in the context of convex analysis).

More complicated convex functions can of course be built by combining the convexity-preserving transformations described below.

Convex Functions on Discrete Point Sets

In algorithm competitions, many functions are defined only at some integer points. In general, they are not convex functions in the sense defined above, because their domains are no longer convex sets. To handle this situation, convexity for functions on a discrete point set must be defined separately. In brief, first linearly interpolate the function, extending its domain to an interval, and then test its convexity.

Figure: epigraph convex discrete
Convex Function on a Discrete Point Set

Let S⊂RS\subset\mathbf R be a discrete point set, meaning that for every closed interval [a,b][a,b], S∩[a,b]S\cap[a,b] is finite. For a function f:S→R∪{±∞}f:S\rightarrow\mathbf R\cup\{\pm\infty\}, define a function f~:R→R∪{±∞}\tilde f:\mathbf R\rightarrow\mathbf R\cup\{\pm\infty\} as follows:

  • When x∈Sx\in S, set f~(x)=f(x)\tilde f(x)=f(x);

  • when x∈(inf⁡S,sup⁡S)∖Sx\in(\inf S,\sup S)\setminus S, let s−=max⁡{s∈S:s≤x}s_-=\max\{s\in S:s\le x\} and s+=min⁡{s∈S:s≥x}s_+=\min\{s\in S:s\ge x\}, and set

    f~(x)=s+−xs+−s−f(s−)+x−s−s+−s−f(s+),\tilde f(x) = \dfrac{s_+-x}{s_+-s_-}f(s_-)+\dfrac{x-s_-}{s_+-s_-}f(s_+),
  • when x∉[inf⁡S,sup⁡S]x\notin[\inf S,\sup S], set f~(x)=+∞\tilde f(x)=+\infty.

Then, if f~(x)\tilde f(x) is convex on R\mathbf R, f(x)f(x) is called convex on SS.

Because convex functions on R\mathbf R are easier to work with, this article uses “convex function” to mean a function on R\mathbf R unless stated otherwise. If a function in this article is given only at some integer points, its values at other real points are determined by the f~\tilde f in the definition; equivalently, we are directly considering the corresponding piecewise-linear function f~\tilde f.

Convex functions on the integers Z\mathbf Z have a more intuitive equivalent definition:

Equivalent Definition of Convexity on Z\mathbf Z

A function f:Z→R∪{±∞}f:\mathbf Z\rightarrow\mathbf R\cup\{\pm\infty\} is convex if and only if

f(x)−f(x−1)≤f(x+1)−f(x)f(x)-f(x-1)\le f(x+1)-f(x)

holds for every x∈Zx\in\mathbf Z.

Proof

This proposition is a direct consequence of the slope characterization of convex functions.

If ff is convex on Z\mathbf Z, then the slopes are nondecreasing, so

Δf(x−1,x)≤Δf(x−1,x+1)≤Δf(x,x+1).\Delta f(x-1,x)\le \Delta f(x-1,x+1) \le\Delta f(x,x+1).

This is exactly the condition above.

Conversely, if the condition above holds, then for any x1<x2x_1<x_2,

Δf(x1,x2)=1x2−x1∑i=x1x2−1(f(i)−f(i−1)).\Delta f(x_1,x_2) = \dfrac{1}{x_2-x_1}\sum_{i=x_1}^{x_2-1}\left(f(i)-f(i-1)\right).

This is the arithmetic mean of all differences satisfying x1≤i<x2x_1\le i<x_2. Increasing x2x_2 by one inserts a larger difference, while increasing x1x_1 by one removes a smallest difference. Both operations increase the mean. This shows that the slope Δf(x1,x2)\Delta f(x_1,x_2) is nondecreasing, so ff is convex on Z\mathbf Z.

In other words, any sequence whose slopes (differences) are nondecreasing can be regarded as a convex function on Z\mathbf Z.

Two Characterizations of Convex Functions

The slope characterization of convex functions can in fact be generalized to the general case.

Slope Characterization of Convex Functions

Let SS be R\mathbf R or a discrete subset of it. Then a function f:S→R∪{±∞}f:S\rightarrow\mathbf R\cup\{\pm\infty\} is convex if and only if its slope

Δf(x1,x2)=f(x2)−f(x1)x2−x1\Delta f(x_1,x_2) = \dfrac{f(x_2)-f(x_1)}{x_2-x_1}

For every x1,x2∈Sx_1,x_2\in S with x1<x2x_1<x_2, this slope is a nondecreasing function of x1x_1 and x2x_2.

Proof

For a function on R\mathbf R, written f(x)f(x), and for x1<x2x_1<x_2, let α∈(0,1)\alpha\in(0,1) and x3=αx1+(1−α)x2x_3=\alpha x_1+(1-\alpha)x_2. Then

Δf(x1,x3)≤Δf(x1,x2)≤Δf(x3,x2)\Delta f(x_1,x_3) \le \Delta f(x_1,x_2) \le \Delta f(x_3,x_2)

is equivalent to

f(x3)−f(x1)1−α≤f(x2)−f(x1)≤f(x2)−f(x3)α.\dfrac{f(x_3)-f(x_1)}{1-\alpha} \le f(x_2)-f(x_1) \le \dfrac{f(x_2)-f(x_3)}{\alpha}.

Both inequalities are equivalent to f(x3)≤αf(x1)+(1−α)f(x2)f(x_3)\le\alpha f(x_1)+(1-\alpha)f(x_2), which is precisely the convexity of f(x)f(x).

For a function on R\mathbf R restricted to a discrete subset SS, written f(x)f(x), the necessity of nondecreasing slopes follows from the convexity of f~(x)\tilde f(x). To prove sufficiency, it is enough to show that Δf~(x1,x2)\Delta\tilde f(x_1,x_2) is also nondecreasing. Let S={si}S=\{s_i\} with sis_i strictly increasing in ii, and suppose si1≤x1≤si1+1s_{i_1}\le x_1\le s_{i_1+1} and si2≤x2≤si2+1s_{i_2}\le x_2\le s_{i_2+1}. Naturally, i1≤i2i_1\le i_2. Let Δi=Δf(si,si+1)\Delta_i=\Delta f(s_i,s_{i+1}). We can show that Δi1≤Δf~(x1,x2)≤Δi2\Delta_{i_1}\le\Delta\tilde f(x_1,x_2)\le\Delta_{i_2}.

There are two cases. If i1=i2i_1=i_2, then Δi1=Δf~(x1,x2)=Δi2\Delta_{i_1}=\Delta\tilde f(x_1,x_2)=\Delta_{i_2}, so the inequality is immediate. Otherwise,

Δf~(x1,x2)=1x2−x1((si1+1−x1)Δi1+(x2−si2)Δi2+∑j=i1+1i2−1(sj+1−sj)Δj).\Delta\tilde f(x_1,x_2) = \dfrac{1}{x_2-x_1}\left((s_{i_1+1}-x_1)\Delta_{i_1}+(x_2-s_{i_2})\Delta_{i_2}+\sum_{j=i_1+1}^{i_2-1}(s_{j+1}-s_j)\Delta_j\right).

Since the slopes on SS are increasing, Δi\Delta_i increases with ii, and therefore Δi1≤Δf~(x1,x2)≤Δi2\Delta_{i_1}\le\Delta\tilde f(x_1,x_2)\le\Delta_{i_2}.

Using this result, take x1<x2x_1<x_2 and α∈(0,1)\alpha\in(0,1), let x3=αx1+(1−α)x2x_3=\alpha x_1+(1-\alpha)x_2, and choose i3i_3 such that si3≤x3≤si3+1s_{i_3}\le x_3\le s_{i_3+1}. Then

Δf~(x1,x3)≤Δi3≤Δf~(x3,x2).\Delta\tilde f(x_1,x_3) \le \Delta_{i_3} \le \Delta\tilde f(x_3,x_2).

Substituting the expression for x3x_3 gives the convexity of f~(x)\tilde f(x).

Nondecreasing slopes can be viewed as an equivalent definition of convexity. Precisely because convex-function slopes are monotone, maintaining slopes commonly requires data structures such as a heap (priority queue) or a balanced tree.

Another equivalent characterization will also be useful. For f:R→R∪{±∞}f:\mathbf R\rightarrow\mathbf R\cup\{\pm\infty\}, consider the region above the graph of the function in the plane:

epi⁡f={(x,y)∈R2:y≥f(x)}.\operatorname{epi} f = \{(x,y)\in\mathbf R^2 : y\ge f(x)\}.

This region is also called the epigraph of ff. Convexity of the function is equivalent to convexity of its epigraph:

Epigraph Characterization of Convex Functions

A function f:R→R∪{±∞}f:\mathbf R\rightarrow\mathbf R\cup\{\pm\infty\} is convex if and only if epi⁡f\operatorname{epi}f is a convex set in R2\mathbf R^2.

Proof

If ff is convex, then for (x1,y1),(x2,y2)∈epi⁡f(x_1,y_1),(x_2,y_2)\in\operatorname{epi}f and any α∈(0,1)\alpha\in(0,1),

αy1+(1−α)y2≥αf(x1)+(1−α)f(x2)≥f(αx1+(1−α)x2).\alpha y_1+(1-\alpha)y_2 \ge \alpha f(x_1)+(1-\alpha)f(x_2) \ge f(\alpha x_1+(1-\alpha) x_2).

Therefore, α(x1,y1)+(1−α)(x2,y2)∈epi⁡f\alpha(x_1,y_1)+(1-\alpha)(x_2,y_2)\in\operatorname{epi}f.

Conversely, if epi⁡f\operatorname{epi}f is convex, then for any x1<x2x_1<x_2 and α∈(0,1)\alpha\in(0,1),

α(x1,f(x1))+(1−α)(x2,f(x2))∈epi⁡f.\alpha(x_1,f(x_1))+(1-\alpha)(x_2,f(x_2)) \in \operatorname{epi}f.

This is equivalent to αf(x1)+(1−α)f(x2)≥f(αx1+(1−α)x2)\alpha f(x_1)+(1-\alpha)f(x_2)\ge f\left(\alpha x_1+(1-\alpha)x_2\right), which is the convexity of ff.

As we will see later, epigraphs connect the infimal convolution of convex functions with the Minkowski sum of convex sets.

Transformations of Convex Functions

We now introduce several convexity-preserving transformations that frequently occur in Slope Trick.

Nonnegative Linear Combinations

For convex functions ff and gg and nonnegative real numbers α,β≥0\alpha,\beta\ge0, the function αf+βg\alpha f+\beta g is also convex. Moreover,

Δ(αf+βg)=αΔf+βΔg.\Delta(\alpha f+\beta g) = \alpha\Delta f + \beta\Delta g.

Thus, if the slopes of convex functions ff and gg are maintained, the slopes of their nonnegative linear combination αf+βg\alpha f+\beta g can be obtained by computing each segment separately.

In slope-maintenance problems, one of the functions often has a simple form, in which case lazy tags can reduce the update complexity. In kink-maintenance problems, finding the slope kinks of f+gf+g only requires merging the slope kinks of ff and gg.

Infimal Convolution (Minkowski Sum)

Another common operation on convex functions is infimal convolution. For functions ff and gg, define

h(x)=inf⁡y∈Rf(y)+g(x−y)h(x) = \inf_{y\in\mathbf R}f(y)+g(x-y)

and call the infimal convolution2 of ff and gg. If ff and gg are both convex, their infimal convolution is also convex.

Figure: epigraph convex minkowski
Interpreting the Illustration

To find the infimal convolution of ff and gg, namely hh, regard every point on the graph of ff (the red dashed curve in the third panel) as the origin and draw a graph of gg in the corresponding coordinate system (the blue dashed curve in the third panel). As the origin of the coordinate system moves along the graph of ff, the outline traced by the moving graph of gg (its epigraph), namely the lower convex hull, is the graph of hh. Thus, every slope segment of hh is either a slope segment of ff or one of gg; the segments have simply been reordered by slope. The roles of ff and gg may be exchanged: moving the graph of ff along the graph of gg gives the same result.

Geometrically, epi⁡h\operatorname{epi}h is the Minkowski sum of epi⁡f\operatorname{epi}f and epi⁡g\operatorname{epi}g. If ff and gg are piecewise-linear functions, then hh is also piecewise linear, and its slope segments can be viewed as the result of merging and then sorting the slope segments of ff and gg.

Proof

Let f,gf,g be convex and let hh be their infimal convolution. Take x1<x2x_1<x_2 and α∈(0,1)\alpha\in(0,1). By the definition of infimal convolution, for any ε>0\varepsilon>0, there exist yi,zi∈Ry_i,z_i\in\mathbf R such that yi+zi=xiy_i+z_i=x_i and

h(xi)+ε>f(yi)+g(zi).h(x_i) + \varepsilon > f(y_i) + g(z_i).

Combining this with the convexity of f,gf,g and the definition of hh gives

αh(x1)+(1−α)h(x2)+ε>αf(y1)+(1−α)f(y2)+αg(z1)+(1−α)g(z2)≥f(αy1+(1−α)y2)+g(αz1+(1−α)z2)≥h(αx1+(1−α)x2).\begin{aligned} \alpha h(x_1)+(1-\alpha)h(x_2) + \varepsilon &> \alpha f(y_1) + (1-\alpha) f(y_2) + \alpha g(z_1) + (1-\alpha) g(z_2)\\ &\ge f\left(\alpha y_1+(1-\alpha)y_2\right) + g\left(\alpha z_1+(1-\alpha)z_2\right)\\ &\ge h(\alpha x_1+(1-\alpha)x_2). \end{aligned}

Since ε>0\varepsilon>0 is arbitrary,

αh(x1)+(1−α)h(x2)≥h(αx1+(1−α)x2).\alpha h(x_1)+(1-\alpha)h(x_2) \ge h(\alpha x_1+(1-\alpha)x_2).

This proves the convexity of hh.

For the geometric statement, strictly speaking, we can prove only

epi⁡f+epi⁡g⊆epi⁡h⊆cl⁡(epi⁡f+epi⁡g).\operatorname{epi} f + \operatorname{epi} g\subseteq \operatorname{epi}h \subseteq \operatorname{cl}(\operatorname{epi} f + \operatorname{epi} g).

Here cl⁡\operatorname{cl} denotes closure.

For any (x,y)∈epi⁡f+epi⁡g(x,y)\in\operatorname{epi} f + \operatorname{epi} g, there are (x1,y1)∈epi⁡f(x_1,y_1)\in\operatorname{epi} f and (x2,y2)∈epi⁡g(x_2,y_2)\in\operatorname{epi} g with x=x1+x2x=x_1+x_2 and

y=y1+y2≥f(x1)+g(x2)≥h(x1+x2)=h(x).y = y_1+y_2 \ge f(x_1)+g(x_2) \ge h(x_1+x_2)=h(x).

Hence (x,y)∈epi⁡h(x,y)\in\operatorname{epi}h, proving epi⁡f+epi⁡g⊆epi⁡h\operatorname{epi} f + \operatorname{epi} g\subseteq \operatorname{epi}h.

Conversely, for any (x,y)∈epi⁡h(x,y)\in\operatorname{epi}h, we have y≥h(x)y\ge h(x). By the definition of hh, for every ε>0\varepsilon>0 there are x1+x2=xx_1+x_2=x such that

y+ε>f(x1)+g(x2).y + \varepsilon > f(x_1) + g(x_2).

Let y1=f(x1)y_1=f(x_1) and y2=g(x2)y_2=g(x_2), so y+ε>y1+y2y+\varepsilon>y_1+y_2. Thus, for every ε>0\varepsilon>0, a point (x1,y1)+(x2,y2)∈epi⁡f+epi⁡g(x_1,y_1)+(x_2,y_2)\in\operatorname{epi} f + \operatorname{epi} g lies on the line segment joining (x,y)(x,y) and (x,y+ε)(x,y+\varepsilon). Letting ε→0\varepsilon\rightarrow 0 yields epi⁡h⊆cl⁡(epi⁡f+epi⁡g)\operatorname{epi}h \subseteq \operatorname{cl}(\operatorname{epi} f + \operatorname{epi} g).

Therefore, epi⁡f+epi⁡g=epi⁡h\operatorname{epi} f + \operatorname{epi} g = \operatorname{epi}h if and only if it is a closed convex set. One sufficient condition is that ff and gg are proper, convex, and lower semicontinuous. This is enough for algorithmic applications; piecewise-linear functions, for example, always satisfy these conditions.

In practice, if one of ff and gg has fewer slope segments, we can insert the shorter list directly into the longer one. Otherwise, small-to-large merging, a meldable heap, or another problem-specific technique may be needed to reduce the overall merge complexity, or an appropriate method may need to be found for the specific problem.

Minimum and Maximum Operations

The maximum of two convex functions is still convex, but the minimum of two convex functions need not be convex.

Many common minimum operations can be transformed into infimal convolution:

Examples
  • f(x)=min⁡y∈[x+a,x+b]g(y)f(x)=\min_{y\in [x+a,x+b]}g(y) is still convex, because it can be written as the infimal convolution

    f(x)=min⁡y∈Rg(y)+0[−b,−a](x−y).f(x) = \min_{y\in\mathbf R}g(y) + 0_{[-b,-a]}(x-y).
  • f(x)=min⁡{g(x−ai)+bi}f(x)=\min\{g(x-a_i)+b_i\} is convex on Z\mathbf Z if g(x)g(x) is convex on Z\mathbf Z and the function defined on the finite set {ai}⊂Z\{a_i\}\subset\mathbf Z, h:ai↦bih:a_i\mapsto b_i, is convex on that discrete set. Indeed, after extension, f~(x)\tilde f(x) can be viewed as the infimal convolution

    f~(x)=min⁡y∈Rh~(y)+g~(x−y).\tilde f(x) = \min_{y\in\mathbf R}\tilde h(y)+\tilde g(x-y).

Therefore, the function f(x)f(x) before extension is also convex.

However, not every minimum operation preserves convexity.

Counterexample

Let g(x)g(x) be convex. The function f(x)=min⁡{g(x−1)+kx,g(x)}f(x)=\min\{g(x-1)+kx,g(x)\} need not be convex.

In some special problems, although the DP transition can be written as the minimum of two convex functions and is difficult to transform into an infimal convolution, the value function nevertheless remains convex. In practice, it is usually necessary to combine tabulation with conjectures to find a suitable slope transition method for such problems.

After understanding convex functions and their common transformations, we can understand Slope Trick DP optimization through specific problems. The example problems in this article are roughly divided into two groups, maintaining kinks and maintaining slopes, to illustrate common operations and implementation details for these two methods. However, as emphasized above, the maintenance method is not the essence of Slope Trick; an appropriate way to maintain slope segments should be chosen according to the needs of the specific problem.

Maintaining Kinks

These problems usually arise when the goal is to minimize a sum of absolute values. Because the absolute value of the value function's slope is not large in such problems, it is more convenient to maintain the points where the slope changes.

Maintaining kinks means maintaining the points at which the slope changes in a piecewise-linear function. Equivalently, for every slope kik_i on segment [li,ri][l_i,r_i], maintain only its endpoints; the slope itself need not be stored separately. Therefore, whenever the slope changes in this type of problem, it should change only by a fixed amount. For example, if we maintain the kink set ξ−s≤⋯≤ξ−1≤ξ1≤⋯≤ξt\xi_{-s}\le\cdots\le\xi_{-1}\le\xi_{1}\le\cdots\le\xi_{t}, this means that on [ξ−1,ξ1][\xi_{-1},\xi_1], the slope is 00; moving left across each kink decreases the slope by one, while moving right across each kink increases it by one. Thus, the slope on [ξ2,ξ3][\xi_2,\xi_3] is 22, the slope on [ξ−3,ξ−2][\xi_{-3},\xi_{-2}] is −2-2, and so on. In formal notation, the function can be written using its slope kinks as

f(x)=f(ξ1)+∑i=−s−1max⁡{ξi−x,0}+∑i=1ℓmax⁡{x−ξi,0}.f(x) = f(\xi_1) + \sum_{i=-s}^{-1}\max\{\xi_i-x,0\} + \sum_{i=1}^{\ell}\max\{x-\xi_i,0\}.

Its minimum is f(ξ−1)=f(ξ1)f(\xi_{-1})=f(\xi_1), and is attained at every point in [ξ−1,ξ1][\xi_{-1},\xi_1].

Figure: epigraph convex kinks

Example: Minimum-Cost Increasing Sequence

[BalticOI 2004] Sequence

Given a sequence of length nn, {ai}\{a_i\}, find a strictly increasing sequence {bi}\{b_i\} minimizing ∑i∣ai−bi∣\sum_i|a_i-b_i|, and output the minimum value and any optimal solution {bi}\{b_i\}.

Solution

First, {bi}\{b_i\} being strictly increasing is equivalent to {bi′}={bi−i}\{b'_i\}=\{b_i-i\} being nondecreasing. Therefore, from {ai′}={ai−i}\{a'_i\}=\{a_i-i\} we can find a nondecreasing sequence {bi′}={bi−i}\{b'_i\}=\{b_i-i\} minimizing the difference, and then recover {bi}\{b_i\}.

Consider the naive DP solution. Let fi(x)f_i(x) be the minimum difference after selecting the first values of {bi′}\{b'_i\}—there are ii of them—and requiring the ii-th value to be no greater than xx, compared with {ai′}\{a'_i\}, taking its first ii values:

fi(x)=min⁡∑j=1i∣aj′−bj′∣ s.t. b1′≤b2′≤⋯≤bi′≤x.f_i(x) = \min\sum_{j=1}^i|a'_j-b'_j|\text{ s.t. }b'_1\le b'_2\le\cdots\le b'_i\le x.

The state transition is readily obtained:

fi(x)=min⁡y≤xfi−1(y)+∣ai′−y∣.f_i(x) = \min_{y\le x}f_{i-1}(y)+|a'_i-y|.

The initial state is f0(x)≡0f_0(x)\equiv 0, and the final answer is min⁡xfn(x)\min_xf_n(x). Using the transformations of convex functions introduced above, transforming fi−1(x)f_{i-1}(x) into fi(x)f_i(x) requires two steps:

  1. First, add ∣ai′−x∣|a'_i-x|. This increases all slope segments in (−∞,ai′](-\infty,a'_i] by −1-1 and all slope segments in [ai′,+∞)[a'_i,+\infty) by 11.
  2. Take the minimum of the resulting function, changing g(x)=fi−1(x)+∣ai′−x∣g(x)=f_{i-1}(x)+|a'_i-x| into fi(x)=min⁡y≤xg(y)f_i(x)=\min_{y\le x}g(y). From the analysis above, this is equivalent to taking the infimal convolution of g(x)g(x) and 0[0,+∞)0_{[0,+\infty)}. The latter has only one slope segment, with slope 00 extending infinitely to the right. Inserting it into the slope segments of g(x)g(x) is equivalent to deleting all positive-slope segments.

Once these operations are clear, all slope segments can be maintained directly with a balanced tree, but the code is complicated. Notice that the slope changes by at most 11 each time in this problem, so the absolute value of every slope is at most nn. Instead of maintaining slope segments directly, it is more convenient to maintain the slope kinks.

Suppose the kink set of f−1(x)f_{-1}(x) is ξ−k≤⋯≤ξ−1≤ξ1≤⋯≤ξℓ\xi_{-k}\le\cdots\le\xi_{-1}\le\xi_{1}\le\cdots\le\xi_{\ell}. Then the two operations above correspond to:

  1. Add a kink at ai′a'_i for a negative-slope segment and a kink at ai′a'_i for a positive-slope segment.
  2. Pop the kinks ξ1,⋯ ,ξℓ\xi_1,\cdots,\xi_{\ell} of all positive-slope segments.

In the actual maintenance, after each operation there are no kinks of positive-slope segments, so the slope kinks have the form ξ−k≤⋯≤ξ−1\xi_{-k}\le\cdots\le\xi_{-1}. Moreover, the operations always occur at the boundary between positive- and negative-slope segments, so it is enough to maintain a max-heap containing all kinks. The two operations correspond to:

  1. Insert ai′a'_i twice.
  2. Pop the top of the heap.

Of course, the minimum value of the current function must also be maintained after each operation. Since there are no positive-slope kinks after an operation, the minimum is the value of the function at the top of the max-heap. Suppose the heap top before each operation is ξ−1\xi_{-1} and the minimum is fi−1(ξ−1)f_{i-1}(\xi_{-1}). Because the popped top is the smallest kink of the positive-slope segments, the minimum equals the function value at that point. Thus, we can directly compute the function value at the heap top before popping, namely

fi−1(max⁡{ai′,ξ−1})+∣max⁡{ai′,ξ−1}−ai′∣=fi−1(ξ−1)+max⁡{0,ξ−1−ai′}.f_{i-1}(\max\{a'_i,\xi_{-1}\})+|\max\{a'_i,\xi_{-1}\}-a'_i|=f_{i-1}(\xi_{-1})+\max\{0,\xi_{-1}-a'_i\}.

The equality of the first terms follows because fi−1(x)f_{i-1}(x) has no positive-slope segments. Therefore, at each step we only need to repeatedly add max⁡{0,ξ−1−ai′}\max\{0,\xi_{-1}-a'_i\} to the minimum value.

This problem also asks us to output one optimal solution. At the end of the final operation, the optimal solution is the heap top, so the value of bn′b'_n can be determined directly. If the ii-th optimal value bi′b'_i is known and we need an optimal solution of fi−1(x)f_{i-1}(x) satisfying x≤b′x\le b', note that because fi−1(x)f_{i-1}(x) is convex, the closer a point is to its global minimum point, the better the solution. Therefore, it is enough to record a global minimum point of fi−1(x)f_{i-1}(x) and take its minimum with bi′b'_i to obtain the optimal bi−1′b'_{i-1}.

The time complexity is O(nlog⁡n)O(n\log n).

#include <iostream>
#include <queue>
#include <vector>

int main() {
  int n;
  std::cin >> n;
  std::vector<int> a(n), b(n);
  for (int& x : a) std::cin >> x;
  for (int i = 0; i < n; ++i) a[i] -= i;
  long long res = 0;
  std::priority_queue<int> max_heap;
  for (int i = 0; i < n; ++i) {
    max_heap.emplace(a[i]);
    max_heap.emplace(a[i]);
    res += max_heap.top() - a[i];
    max_heap.pop();
    b[i] = max_heap.top();
  }
  std::cout << res << '\n';
  for (int i = n - 2; i >= 0; --i) b[i] = std::min(b[i], b[i + 1]);
  for (int i = 0; i < n; ++i)
    std::cout << (b[i] + i) << (i == n - 1 ? '\n' : ' ');
  return 0;
}

Template problems:

Example: The Case with a Bounded Transition

[NOISG 2018 Finals] Safety

Given a sequence of length nn, {ai}\{a_i\}, find a sequence {bi}\{b_i\} satisfying ∣bi−bi−1∣≤h|b_i-b_{i-1}|\le h for all $1 [!note]- Solution

The content is broadly similar to the previous problem, except that the constraint on the sequence {bi}\{b_i\} has changed. Likewise, let fi(x)f_i(x) be the minimum difference when the ii-th value is xx, for the first ii values:

fi(x)=min⁡∑j=1i∣aj−bj∣ s.t. ∣bj−1−bj∣≤h,∀1<j≤i, bi=x.f_i(x) = \min\sum_{j=1}^i|a_j-b_j|\text{ s.t. }|b_{j-1}-b_j|\le h,\forall 1<j\le i,~b_i=x.

The state transition is

fi(x)=∣ai−x∣+min⁡∣y−x∣≤hfi−1(y).f_i(x) = |a_i-x| + \min_{|y-x|\le h} f_{i-1}(y).

The initial condition is f0(x)≡0f_0(x)\equiv 0. The final answer is still min⁡xfn(x)\min_xf_n(x).

Decompose the state transition into operations on convex functions. It has two steps:

  1. First take the minimum over fi−1(x)f_{i-1}(x), obtaining min⁡∣y−x∣≤hfi−1(y)\min_{|y-x|\le h} f_{i-1}(y). This is the infimal convolution of fi−1(x)f_{i-1}(x) and 0[−h,h](x)0_{[-h,h]}(x).
  2. Then add ∣ai−x∣|a_i-x| to the resulting function.

Again, because the slope changes by only one each time, we can consider maintaining kinks. The two operations can then be described as:

  1. Move all negative-slope segments hh units to the left, and all positive-slope segments hh units to the right.
  2. Insert aia_i twice.

For this problem, it is clearly convenient to maintain the positive- and negative-slope segments separately. Since the operations are concentrated mainly around the zero-slope segment, consider using a two-heaps structure, that is, a max-heap and a min-heap to maintain the kinks of the negative- and positive-slope segments. Apply the overall translation of the kinks in each heap with a lazy tag. The second operation needs to insert aia_i into each heap, and after the insertion the top of the max-heap may no longer be no greater than the top of the min-heap. In that case, swap the two heap tops until the ordering is restored.

Finally, consider how to update the minimum during the operations. The first translation operation does not change the minimum, so only the heap-top swaps need to be considered. Suppose ξ−1>ξ1\xi_{-1}>\xi_1. When the heap tops ξ−1\xi_{-1} and ξ1\xi_1 are swapped, the function changes from

max⁡{0,x−ξ−1}+max⁡{0,x−ξ1}\max\{0,x-\xi_{-1}\}+\max\{0,x-\xi_1\}

to

max⁡{0,x−ξ1}+max⁡{0,x−ξ−1}.\max\{0,x-\xi_{1}\}+\max\{0,x-\xi_{-1}\}.

The function shape does not change during this process; it is only shifted downward by ∣ξ−1−ξ1∣|\xi_{-1}-\xi_1|. Therefore, to keep the function unchanged before and after swapping the heap tops, it is enough to add ∣ξ−1−ξ1∣|\xi_{-1}-\xi_1| to the minimum.

The algorithm still has time complexity O(nlog⁡n)O(n\log n), because after each element is added, the heap-top swap is performed at most once.

#include <iostream>
#include <queue>
#include <vector>

int main() {
  int n;
  long long h;
  std::cin >> n >> h;
  std::priority_queue<long long> max_heap;
  std::priority_queue<long long, std::vector<long long>, std::greater<>>
      min_heap;
  long long lt = 0, rt = 0;
  long long res = 0;
  for (; n; --n) {
    long long x;
    std::cin >> x;
    lt += h;
    rt += h;
    max_heap.emplace(x + lt);
    min_heap.emplace(x - rt);
    auto l = max_heap.top() - lt;
    auto r = min_heap.top() + rt;
    while (l > r) {
      max_heap.pop();
      min_heap.pop();
      res += l - r;
      max_heap.emplace(r + lt);
      min_heap.emplace(l - rt);
      l = max_heap.top() - lt;
      r = min_heap.top() + rt;
    }
  }
  std::cout << res << std::endl;
  return 0;
}

Template problems:

Maintaining Slopes

For some other problems, maintaining slopes is more convenient. Such problems can often also be solved using the idea of regretful greedy or simulated min-cost flow. In the min-cost flow model, the minimum cost is often a convex function of the flow, which provides the foundation for using Slope Trick.

Example: Stock Trading

Codeforces 865 D. Buy Low Sell High

Given nn days of stock prices {pi}\{p_i\}, all positive, with an initial holding of 00. Each day, one share may be bought, one share may be sold, or no trade may be made. Find the maximum profit after nn days.

Solution

First consider the naive DP solution. Let fi(x)f_i(x) be the maximum profit after day ii when holding x≥0x\ge 0 shares:

fi(x)=max⁡{fi−1(x−1)−pi,fi−1(x),fi−1(x+1)+pi}.f_i(x) = \max\{f_{i-1}(x-1)-p_i,f_{i-1}(x),f_{i-1}(x+1)+p_i\}.

The initial state is f0(0)=0f_0(0)=0, and for every x≠0x\neq 0, f0(x)=−∞f_0(x)=-\infty. The answer is fn(0)f_n(0).

Transforming fi−1(x)f_{i-1}(x) into fi(x)f_i(x) requires two steps:

  1. Take the supremal convolution of fi−1(x)f_{i-1}(x) with the piecewise-linear function h~(x)\tilde h(x) corresponding to

    hi(x)={pi,x=−1,0,x=0,−pi,x=1h_i(x) = \begin{cases}p_i,&x=-1,\\0,&x=0,\\-p_i,&x=1\end{cases}

    (which is clearly concave);

  2. This gives the function finite values on [−1,0)[-1,0), which conflicts with the requirement x≥0x\ge 0, so take only the part of the function on [0,+∞)[0,+\infty).

Translated into changes to slope segments, these are:

  1. Insert a slope segment of length 22 and slope −pi-p_i;
  2. Delete, among the slope segments with finite slope, the segment with the largest slope and length 11.

Since the lengths of slope segments are always integers, we may maintain several slope segments of length one and record only the slope of each segment. Since we only need insertion and maximum queries, a max-heap is enough. The two operations are:

  1. Insert −pi-p_i twice.
  2. Pop the heap top.

We also need to maintain the value of fi(0)f_i(0). The function obtained after the first operation has value at x=−1x=-1 equal to fi−1(0)+pif_{i-1}(0)+p_i, so its value at x=0x=0 is that value plus the heap top that is about to be popped, which is the slope of the function on [−1,0][-1,0]. Because truncation does not change the value at x=0x=0, this is fi(0)f_i(0).

Comparing this implementation with the code for Minimum-Cost Increasing Sequence above shows that this algorithm is equivalent to finding the minimum cost of changing the stock prices into a nonincreasing sequence.

The time complexity is O(nlog⁡n)O(n\log n).

#include <iostream>
#include <queue>
#include <vector>

int main() {
  int n;
  std::cin >> n;
  std::vector<int> a(n);
  for (int& x : a) std::cin >> x;
  long long res = 0;
  std::priority_queue<int> max_heap;
  for (int x : a) {
    max_heap.emplace(-x);
    max_heap.emplace(-x);
    res += x + max_heap.top();
    max_heap.pop();
  }
  std::cout << res << '\n';
  return 0;
}

Template problem:

Example: Moving Soil and Stones

[USACO16OPEN] Landscaping P

Given sequences of length nn, {ai}\{a_i\} and {bi}\{b_i\}, representing the amount of soil already in and the amount of soil required by garden ii, respectively (neither extra soil nor a shortage is allowed). Buying one unit of soil and putting it in any garden costs XX, removing one unit of soil from any garden costs YY, and transporting one unit of soil from garden ii to garden jj costs Z∣i−j∣Z|i-j|. Find the minimum cost of satisfying all garden demands. (ai,bi≤10a_i,b_i\le 10.)

Solution

Consider the naive DP solution. Let fi(x)f_i(x) be the minimum cost after satisfying the demands of the first ii gardens, when a net surplus of xx units of soil is transported to later gardens. If x<0x<0, this means that a net shortage of ∣x∣|x| units must be transported from later gardens. Then the state transition can be written as

fi(x)=min⁡y∈Rfi−1(y)+∣y∣Z+h((x−y)+(bi−ai)).f_i(x) = \min_{y\in\mathbf R} f_{i-1}(y) + |y|Z + h((x-y)+(b_i-a_i)).

Here, h(δ)h(\delta) denotes the cost when the net amount of soil purchased for the current garden is δ\delta:

h(δ)=max⁡{0,δ}X+max⁡{0,−δ}Y=max⁡{δX,−δY}.h(\delta) = \max\{0,\delta\}X + \max\{0,-\delta\}Y = \max\{\delta X,-\delta Y\}.

This is clearly convex. The meaning of the state transition is:

  • When the net surplus of soil among the first i−1i-1 gardens is yy, the minimum cost is fi−1(y)f_{i-1}(y).
  • The cost of transporting the net surplus (or shortage) between gardens ii and i−1i-1 is ∣y∣Z|y|Z.
  • By buying and selling, the amount of soil in garden ii is adjusted from aia_i to bib_i, and the net surplus is adjusted from yy to xx, at minimum cost h((x−y)+(bi−ai))h((x-y)+(b_i-a_i)).

The initial state is f0(0)=0f_0(0)=0, and for every x≠0x\neq 0, f0(x)=+∞f_0(x)=+\infty. The answer is fn(0)f_n(0).

Transforming fi−1(x)f_{i-1}(x) into fi(x)f_i(x) can be divided into three steps:

  1. First, add ∣x∣Z|x|Z, obtaining fi−1(x)+∣x∣Zf_{i-1}(x)+|x|Z.
  2. Then take the infimal convolution with h(x)h(x), obtaining min⁡y∈Rfi−1(y)+∣y∣Z+h(x−y)\min_{y\in\mathbf R}f_{i-1}(y)+|y|Z+h(x-y).
  3. Finally, shift the function (bi−ai)(b_i-a_i) units to the left.

Converted into operations on slope segments, the three steps are:

  1. Add −Z-Z to all slope segments left of the origin, and add ZZ to all slope segments right of the origin.
  2. Replace every slope segment smaller than −Y-Y by −Y-Y, and every slope segment greater than XX by XX.
  3. Shift all slope segments (bi−ai)(b_i-a_i) units to the left.

In the original problem, aia_i and bib_i are small, so it is enough to maintain several slope segments of length 11. Although there are infinitely many slope segments, their upper and lower bounds are XX and −Y-Y, and there are only a few segments strictly between them. Since there are no insertion operations, two stacks can maintain the slope segments on the two sides of the origin, with interval additions and interval extrema handled by lazy tags. The three operations above correspond to:

  1. Apply lazy tags to the two stacks, adding −Z-Z on the left and ZZ on the right.
  2. Whenever an element is popped from a stack, take its maximum with −Y-Y and its minimum with XX. If the left stack is empty, pop −Y-Y; if the right stack is empty, pop XX.
  3. Pop (bi−ai)(b_i-a_i) elements from the top of the left stack and insert them into the right stack; when bi−ai<0b_i-a_i<0, do the reverse.

When swapping stack tops, update the answer: moving left subtracts the current slope, while moving right adds the current slope.

The algorithm has complexity O(nmax⁡{ai,bi})O(n\max\{a_i,b_i\}).

#include <iostream>
#include <stack>

int main() {
  int n;
  long long x, y, z;
  std::cin >> n >> x >> y >> z;
  std::stack<long long> neg, pos;
  long long lt = 0, rt = 0;
  long long res = 0;
  for (; n; --n) {
    int a, b;
    std::cin >> a >> b;
    lt -= z;
    rt += z;
    for (; b < a; ++b) {
      auto l = -y;
      if (!neg.empty()) {
        l = std::max(l, neg.top() + lt);
        neg.pop();
      }
      pos.emplace(l - rt);
      res -= l;
    }
    for (; b > a; --b) {
      auto r = x;
      if (!pos.empty()) {
        r = std::min(r, pos.top() + rt);
        pos.pop();
      }
      neg.emplace(r - lt);
      res += r;
    }
  }
  std::cout << res << std::endl;
  return 0;
}

Template problems:

Problems for Practice

This article concludes with some problems from algorithm competitions that can be solved using Slope Trick, for practice.

References and Notes

Footnotes

  1. Different textbooks may use different names for convex functions. ↩

  2. Also called min⁡\min convolution, inf⁡\inf convolution, or (min⁡,+)(\min,+) convolution. ↩

This content comes from OI Wiki: Slope Trick Optimization. See the original for authors and revision history. AIOJ has adapted the formatting, in-site links, and resource paths.

Content is shared under CC BY-SA 4.0 and SATA license; additional terms are governed by the original notice. Thanks to the OI Wiki authors and contributors; per the SATA terms, please visit the OI Wiki repository and star it to show your support.