Atcoder Regular Contest 104 (ARC 104) E Random LIS に関する記事です.

問題文へのリンク

https://atcoder.jp/contests/arc104/tasks/arc104_e

経緯

過去問埋めで解いてみようとしましたが,全然わかりませんでした. 公式解説 を読んでもやっぱりわからず, けんちょんさんの解説 を読んで,なんとか理解することができました.

解法

例えば,N = 4 として,数列 10 7 10 15 と数列 5 1 5 2000 は, 数値の差こそあれ,大小関係は同一である.これらを 1 0 1 2 というパターンとして 1つのグループとしてまとめることにする.以下を実行する.

  • 全パターンを列挙する.
  • 各パターンについて,
    • LISの長さを求める.
    • そのパターンに属する数列の数を数える.

グループがいくつあるかは, Ordered Bell number として知られているということである.N = 6 の場合には,4683個. 丁寧に列挙することもできるであろうが,$6^6 = 46656$ であるから,0 から N-1 までの 数の N 個の並びから,不適なものを弾いても十分速い. 各グループに属する数列では,LIS の長さは同じであり,N <= 6 だからこれを求めるのは容易である. 各グループに属する数列の数を求めるのが主要なタスクとなる.

$\{0, 1\} \cup \{A_i + 1\mid i = 1, \ldots, N\}$ を昇順にソートして $p_0, p_1, .., p_M$ とし,$P_i$ を整数の半開区間 $[p_i, p_{i+1})$ とする.

パターンを1つとる.パターン中に現れる数が $0, 1, \ldots, D-1$ だとする. 各 $d \in [0, D)$ について,これが現れる位置を $q_1, \ldots, q_k$ としたとき,$\min(A_{q_1}, \ldots, A_{q_k})$ を $B_d$ とする. たとえば,パターン 2 2 2 0 1 1 については,$B_0 = A_3$, $B_1 = \min(A_4, A_5)$, $B_2 = \min(A_0, A_1, A_2)$ である. すると,パターンに属する数列の数は,数列 $( x_d | d \in [0, D) )$ であって $x_d \in [1, B_d + 1)$ を満たすものの数に等しいので,これを数えることにする.

動的計画法による. 「長さ i の列 $( x_d | d \in [0, i) )$ で $x_d \in [1, B_d + 1)$ を満たし,$ x_{i-1} \in P_j $ であるもの」の集合を $S_{i,j}$ とし,dp[i][j] を,$S_{i,j}$ の要素の数とする. 普通に dp[i][j] → dp[i+1][j’] の遷移を書こうとすると, j = j’ の時にうまくいかない. そこで,次のことに注目する: 長さ i の列 $(x_d \mid d \in [0, i) )$ について,次の2つは同値である.

  • $( x_d \mid d \in [0, i) ) \in S_{i,j}$
  • $k < i$, $u < j$ が存在して,以下が成り立つ.
    • $(x_d \mid d \in [0, k) ) \in S_{k, u}$
    • 各 $e \in [k, i)$ に対して,$B_e + 1 \geq p_{j+1}$
    • $i - k \leq p_{j+1} - p_j$

そこで,以下のように遷移を定義することができる:

  dp[i][j] ← dp[k][u] * binom(p[j+1] - p[j], i - k)
    where
      * i > k  and
      * j > u  and
      * i - k <= p[j+1] - p[j]  and
      * forall e in [k, i).  B[e] + 1 >= p[j+1]

ACコード

https://atcoder.jp/contests/arc104/submissions/25160111