CODE THANKS FESTIVAL 2018-H:Median Game

これはわかればシンプルで楽に解けるので好き。

解法

このゲームでは,ある列の中央値がゲームのスコアになり,それを求めよと言われている(偶数のときは2つ候補があるが,大きいほうをとる)。中央値を求める問題では二分探索が有効である。中央値がx以上となるか?という質問に答えるには,数列の中にxより以上の数が半分以上含まれるかを調べるだけでよく,これは比較的容易にできるためである。

それでは,「ゲームのスコアはx以上になるか?」という問題に答えよう(この問題はxについて答えが単調なので,二分探索が使える)。このとき,Aliceはスコアを大きくしたいので,x以上の数を増やしたいはずである。一方Bobは,スコアを小さくしたいので,xより小さい数を増やしたいはずである。この2人の戦いをdpによって見守ろう。

  • dpAlice[i]:上からi枚目以降のカードが残っているときにAliceの手番で,(x以上の個数)-(x未満の個数)の最大値
  • dpBob[i]:上からi枚目以降のカードが残っているときにBobの手番で,(x以上の個数)-(x未満の個数)の最小値

dpの遷移であるが,とりあえずAliceの手番のときを考えよう。今回はこのdpにO(N^2)かけてよいので。i\lt j \leq N+1について,区間[i,j-1]のカードをとり,j枚目以降のカードを残してBobに手番を渡すとしよう(j=N+1のときはゲーム終了という意味)。これらのカードの総和をSとすると,Sxの大小によってdpBob[j]1を足すか-1を足すかすればよい。この結果のjについての最大値がdpAlice[i]である。Bobの手番のときも同様である。
dpの遷移は後ろから,つまりi=Nから行うことに注意。ゲームでdpをするときの定番だろう。「ゲームのスコアはx以上になるか?」という問題の答えは,dpAlice[1]\geq 0のときYes,そうでないときNoである。

実装

Submission #4127440 - CODE THANKS FESTIVAL 2018
実装は軽い。dp配列の初期化だけ注意。


本番はほとんど問題文を読まなかったが,もったいなかったかもしれない。