以下、すべて0-basedに直して考えている。
最終形は210∣43∣8765のように、0,1,...,N−1をいくつかの連続部分列に区切って各区間を反転させたものになっている。
dp[x]= 先頭からx個の階段に0,1,...,x−1を有効な順番で並べる場合の最小交換数
としてDPができそう。
DPの遷移を考える。位置0,1,...,x−1に人0,1,...,x−1を配置済みとして、位置xからx,x+1,...,y−1を逆順に並べる場合のコストをf[x][y]とすると、dp[y]←max(dp[y],dp[x]+f[x][y])のように配るDPがO(N2)でできる。
次にfの求め方を考える。与えられた列の中に散らばっている数x,x+1,...,y−1を位置x,x+1,...,y−1に逆順で整列させる時、c[i][j]:= 数iの左にあるj以上の数の総数として、だいたいc[x][x]+c[x+1][x]+...+c[y−1][x]回の交換をしてx,x+1,...,y−1を前のほうに持ってくることになるが、この際、与えられた列上でのx,x+1,...,y−1の順番を考えた時に、既に転倒が起きているぶんの交換はしなくてよい。そこで、inv[x][y]:= 与えられた列からx,x+1,...,y−1を抜き出した部分列の転倒数、とすると
f[x][y]=c[x][x]+...+c[y−1][x]−inv[x][y]
と求まる。cは累積和と同じように構成できて、さらにその累積和C[x][y]:=c[0][y]+...+c[x−1][y]を取っておけば
f[x][y]=C[y][x]−C[x][x]−inv[x][y]
と求まる。
最後にinvの作り方を考える。ここではinv[x][y−1]とinv[x][y]の差分、つまり、与えられた列上のx,x+1,...,y−2に対応する部分列に(与えられた順番通りに)y−1を挿入した時の転倒数の増分を考える。この増分は与えられた列上でy−1の後ろにあって[x,y−1)に含まれる数の総数に等しい。y−1の後ろよりも前にある数のほうが(cを使って)表しやすいので、さらにこれを(y−1−x)−(y−1の前にあって[x,y−1)に含まれる数の総数)と言い換える。この増分は上で求めたcを使って表せて、結局
inv[x][y]←inv[x][y−1]+(y−1−x)−(c[y−1][x]−c[y−1][y])
と遷移できる。
これで、全体としてO(N2)で計算できたことになる。