Official

F - Game against Robot Editorial by maroonrk_admin


一般性を失わず,\(A_1 \geq A_2 \geq \cdots \geq A_N\) であるとします.

\(p\) が固定された場合の問題を考えます. この時の解法は次のようになります.

  • \(p_i\) の昇順にカードを並べ,その番号を \(x_1,x_2,\cdots,x_N\) とする.その後,\(i=1,3,\cdots,N-1\) に対して以下の操作を行う.なお,\(s\) は優先度付きキュー,\(ans\) は答えを表す変数である.
    • \(s\)\(A_{x_i}\)\(A_{x_{i+1}}\) を追加する.
    • \(s\) から最大の要素を取り出し,\(ans\) に加算する.

次に,\(p\) を動かして数え上げを解きます. 各 \(1 \leq k \leq N\) について,\(ans\)\(A_k\) が足される回数が分かればいいです. ここでは,ほとんど同じことですが,\(ans\)\(A_k\) 以上の値が足される回数を求めることにします.

数列 \(x\) の各要素を,\(x_i \leq k\) であるか否かで分類し,\(01\)\(y\) を作ることにします.\(x_i \leq k\) である要素を \(1\) に対応させます. \(p\)\(N!\) 通り試すことは,\(0\)\(N-k\) 個,\(1\)\(k\) 個含む \(01\)\(y\) をすべて試すことに対応します.ただし,同じ \(01\) 列が \((N-k)!k!\) 回登場します.

\(y\) を一つ決め打った時,\(ans\)\(A_k\) 以上の値が足される回数は次のように求められます.

  • \(y\) の後ろ \(i\) 個にある \(1\) の個数を \(cnt(i)\) で表す.
  • この時,\(k-\max_{i=0,2,4,\cdots,N}(cnt(i)-i/2)\) 回,\(ans\)\(A_k\) 以上の値が足される.

これは,優先度付きキューに入っている \(A_k\) 以上の値の個数を考えるとわかります.

\(\max_{i=0,2,4,\cdots,N}(cnt(i)-i/2)\) の部分が本質的に難しい部分です. まず,\(0\)\(-1\) に変換することで,\(-1,1\)\(y'\) を作ります. \(y'\) の後ろ \(i\) 個の和を \(suf(i)\) で表すと, \(\max_{i=0,2,4,\cdots,N}(cnt(i)-i/2)=\lfloor \max_{0 \leq i \leq N}suf(i)/2 \rfloor\) が成り立ちます.右辺の \(\max\)\(i\) の値域は偶数に限定されないことに注意してください.

\( \max_{0 \leq i \leq N}suf(i)\) の値を決め打ち,\(h\) であるとします. この時条件を満たす \(y'\) の個数を数えてみます. まず,\(suf(i)\) を最大化する \(i\) のうち,最大のものを \(m\) とおきます. ここで,\(y'\) の後ろ \(m\) 項について,それらを左右反転し,さらに \(-1,1\) を入れ替えたとします. こうして得た数列を \(z\) とおきます. ここで \(z\) は,以下の条件を満たす数列です.

  • \(z\) の総和は \(2k-N-2h\)
  • \(z\) の prefix-sum は,すべて \(2k-N-2h\) 以上である.

ここで逆に,上記の \(2\) 条件を満たす \(z\) があれば,対応する \(y'\) を一意に決定することが可能です. よって,\(y'\) の個数を求める代わりに,\(z\) の個数を数えればよいです.

\(z\) の個数は,カタラン数の式を求めるのと同様に,鏡写しにしたパスの個数を引くことを考えれば,簡単なコンビネーションの式で書けます.あとは,\(h\) を動かしてここで得た式の和を取ればよいですが,これは累積和を使えば,\(k\) に寄らない前計算 \(O(N)\) 時間,各 \(k\) あたり \(O(1)\) 時間で計算できます.

計算量は全体で \(O(N)\) です.

posted:
last update: