人間だけど競プロやる

解けなかった問題を理解できたら記事を投稿します。日本語の解説が見つからなかったもの中心。

AtCoder Regular Contest 131 (ARC131) D. AtArcher


公式解説が丁寧だけど、累積和の理解に時間がかかったのでメモしておく。
公式とは少し違うみたい。


距離D毎に射る。座標0付近を中心に左右にほぼ均等に割り振る。中心を0から距離Dより離す必要はない。
よって中心を0からDまで試せば良い。
(ここまで公式解説を参考に)
(実装上は左端を求めたほうが多分楽)

ここから最初に射る位置を x として x mod D = p で分類して考える。

わかりやすいように、たまたま p=0 だったとする。

f:id:bqn2:20211208011744j:plain
fig.1

fig.1のような図を考える。
最初に射る位置を x とすると、2射目以降 x + nD (n=1,2...) の位置を射るので、Dで割ったあまりは常にpとなる。 よってp毎に全射の合計が求まれば、その最大値が答え。

f:id:bqn2:20211208012548j:plain
fig.2


そこでfig.2のようにD毎の範囲を移動してみると、連続する範囲(横向き)にスコアを足して、p毎に(縦向きに)合計を計算できれば、その最大値が求める答えになる。
これは、0,1,2...射目に得点の境界をまたぐなら、その範囲にスコアを足す累積和(imos法)で答えることが出来る(境界が無いなら全体にスコアを足す)。
縦向きの合計は、自然に求まるので、最大値を答えれば良い。

N回のループの中で、スコアの境界があったらimos法用の配列を2箇所更新するだけなので、十分間に合う(配列のサイズはD)。
(一射の中にスコアの境界が大量に存在する可能性があるけど、全体でスコアの境界は 2 \times M しかない)
(実装上は左端がp=0になるように全体の座標をスライドさせると楽)