2019年9月6日金曜日

AISing Programming Contest 2019 D - Nearest Card Game

AISing Programming Contest 2019 D - Nearest Card Game

シミュレーションしてみると(時系列を無視すれば)

  1. 高橋君が上から何枚か取って
  2. 残りを青木君が上から同じ枚数取って
  3. さらに残りを二人で上から交互に取る

という仕組みになっていることがわかる。

高橋君が手順1で上からll枚、つまり区間[Nl,N)[N-l, N)を取るとし、青木君が手順2で区間[N2l,Nl)[N-2l, N-l)を取るとして、与えられたルールに従うためのllの条件を考える。

まず、青木君が取るもっとも大きい数はANl1A_{N-l-1}である。したがって、青木君が最初に決めた数をxxとするとき、xmax(ANl1x,0)x- \max(A_{N-l-1}-x, 0)以上の数が書かれたカードはすべて青木君が取っていなければならないことになる。ここで、

f(y):=f(y) := yy以上の数が書かれたもっとも左のカードのインデックス

とする。( f(y)f(y)は二分探索で求まる。) ffを使って上の条件を表すと、青木君は少なくとも区間[f(xmax(ANl1x,0)),Nl)[f(x- \max(A_{N-l-1}-x, 0)), N-l)を取らなければならず、これは、青木君が手順2で取るカードの枚数が(Nl)f(xmax(ANl1x,0))(N-l)-f(x- \max(A_{N-l-1}-x, 0))以上であることを意味する。この数をg(l,x)g(l, x)で表すとき、g(l,x)g(l, x)ll以下でなければならない。したがって、ルールに従った取り方では、g(l,x)lg(l, x) \le lであるような最大のl=:lmaxl =: l_{\max}が、手順1, 2で実際に取った枚数になる。g(l,x)g(l, x)llについて単調増加なのでlmaxl_{\max}はやはり二分探索で求まる。

lmaxl_{\max}が求まったら、高橋君の点数は区間[Nlmax,N)[N-l_{\max}, N)の総和と[0,N2lmax)[0, N-2l_{\max})をひとつおきに取った和(00から始まるか11から始まるかは偶奇による)の合計になるため、どちらも累積和を計算しておけばO(1){\mathcal O}(1)で求まる。