5完。Dまでめちゃくちゃ調子よかったのに、EのDPでつまづいて、Fで破壊された。
A - Median?
ソートして中央値を求めるが、bを保存しておく必要があるのをうっかりした。今考えると解説みたいな方法も思いつくけど、思いついてから正しいと確信するまでの時間がかかりそうなので、やはり本番で採用した方針がよい。
B - Distance Between Tokens
1個目の位置を記録しておいて、2個目を見つけたら計算して出力。
C - Max - Min Query
簡単だけど、実装しながら「これC!?」ってなってた。大量に削除するからmultisetはだめでmapで個数を管理する(と思ってたけど今考えたら全体でO(Q)個しか削除しないからmultisetでよかったよなんで気づかないんだ)。削除してxが0個になるときはx自体をeraseする必要があることに注意する。解説を見ると、end()から一つ戻る代わりにrbegin()でいいんだね。
D - FizzBuzz Sum Hard
包除。N以下の最大のAの倍数をAで割ったものはN/A(切り捨て)で求められる。N以下のAの倍数をAで割ったものの総和を求めてAを掛ければいい。A=Bのときも大丈夫(これが感覚でわからなかった)。
E - Distance Sequence
難しそうだけどDPすればいい。Aをi番目まで決めて最後がjのときの通り数でDP。i番目より後へはA_iしか影響しないので、そこでまとめて計算することができる(これがDP)。愚直にやると間に合わないが、累積和を使えばできる。が、好みではないので逐次計算していく。A_iの範囲は0以上M未満としても答えは同じなのでそうする。まずK以上M未満の総和を求めておき、dp[j]を更新したらj+Kを引いてj-Kを足す(範囲外であれば操作しない)、とすると合わない。かなりややこしいが、更新後に足すならj+1-Kの位置だ(今回のj-Kは既に入っている)。そこでj-Kを足す操作を更新前に持ってきたが、これを提出してWA。K=0のときのケアを、更新後に足す場合しかしてなかった(実装を変えるときにケアしたはずのところが抜けるのよくある)(このくらいのDPはできるが、やはり苦手ではあるので負荷が高く余裕がなくなりミスが増える)。原因がわかったので提出してACを取っておいたが、どう書くのが自然だったかわからないままだった。今思うと、K=0自体が微妙な設定なのでそんなもんかなと。
F - Operations on a Matrix
解けそうだなとはわりとすぐ思うけど、脳破壊系の実装。クエリ3から見てi行目に対する最後のクエリ2のxと時刻を保存しておく(これは長さNのvectorにxと時刻を上書きしていったものから取得できる)。クエリ1も保存しておく。クエリ3は、コピーして片方は対応するクエリ2の時刻でソートしておく(もう片方は当然クエリ3が来た時刻でソートされている)。サイズMのBITで区間加算点取得をする。各時刻について順番に処理していく(ここが最後まで見えなかったやり方で、最初はクエリ1だけで回していた)。クエリ2の時刻でソートしたクエリ3では、BITで0からjまでの総和が点jの値なので保存しておく(保存場所は「そのクエリ3の時刻」とすればいい)。クエリ3は、その保存した値と今の値の差をベースとなるクエリ2のxに足して出力。クエリ1はBITでLとRにxを足して引いていもす法みたいにする。
これは本当にきつかった。この方針がぼんやりとしか見えてない状態で答えを彫り出さないといけない。1時間あったのに間に合わず、7分オーバー。ちゃんと解けてはいると思うけど、どのくらい無駄な処理を書いたのかも全然わかってない。