ABC276

6完2ペナ。今朝インフルエンザの予防接種やったので体調は微妙だったか。んにしても苦手セットだった。「時間さえあればG解けたのになあ」って言いてえよ。それが言えないんじゃ話にならない。

A - Rightmost

少し迷ってstring::findで書いて合わず「最後に現れる」を見て(こういう関数あってくれと思いながら)rfindで書いて最初の文字を0番目で出力していると気づき非負なら1を足す処理を付け足す。いい動きをしているが、絶妙に遠回りしている。

B - Adjacency List

問題文読むの大変すぎるだろ。普通にvectorvectorでグラフ構築してソートして出力する。

C - Previous Permutation

greaterを指定してnext_permutationするだけ。C問題で2分切ってる。反対側からK番目みたいな問題だと思ってサンプル見たら違った。

D - Divide by 2 or 3

(回数はカウントしておいて)割れるだけ割っていい気がする。最終的に全部同じになったとすると、そこに含まれる2や3の個数も同じ。素因数分解の一意性がここで出てくるかあ。ということで割れるだけ割ってしまい一つでも違うのがあったらダメ。そうでなかったら割った回数が一番少なかったやつに合わせる(そのぶんの回数を引く)。全部必要かつ十分(雑な言い方だな)になっていると思う。提出してWA。3分くらい考え直して(考察もコードも)正しいと思うのでEへ行った。

Fを通して戻ってきたが、回数を引くときNを掛けるのを忘れていた。N回まわすforループの中から持ってきたからか?

E - Round Trip

ループで一見難しそうだが、一歩目を固定してしまえばただのBFSになる(UnionFindは思いつかなかったな)。最近こういう実装普通にできるようになってきたので、stringのvectorで番兵も置かず普通にBFSした。4回BFSする(ほんとは3回でいいけどさすがにしなかった)。スタート地点の隣からスタート地点へ。ただし、その2点間の直接の移動は禁止。WAになったけど正しそうに見える。7分くらいでFへ。

直接の移動を距離が4未満で判定していたが、スタート地点の隣からなので距離は0ではなく1から始めるのだった。問題文読んだときも「n>2でいいじゃん」と思ってたのになあ。こういうミスでレーティング下がるのはいいけど難しい問題を考える時間が削られるのが痛すぎる。

F - Double Chance

K*Kの図を描くと、Aが昇順ならわかりやすい。実際はそうじゃないけど、同じ考え方は使える。挿入が厄介そうだが、A_iが小さいので個数で管理できる(今思うと大きくても座圧で簡単そうだ)。挿入するとき、例えば4だったら3の後4の前という位置に入れることにする。このとき必要な情報は自分より小さいものの個数と自分以上のものの数の和。このへんけっこう混乱して遅延セグ木が必要なのではと恐れたりしていたが単に加算のセグ木でいい。個数は簡単で、数で重み付けした和は単にA_iを足してupdateするだけ。

G - Count Sequences

さすがに難しい。包除原理が単に二項係数で行けるかもと思ったけど3の倍数にする場所に3をいくつ使うかによって他の部分の自由度が変わるのでだめだった。この単純な方針だと仕切りの入り方がけっこう好み。

(追記)解説が全然読めなかったけど、仕切りで区切られたN+1個の塊をmod 3で固定すればよさそうなのでそれで解いた。なんか今回はコンテスト中から仕切りとボールの絵を逆にしてたのでそれで書く。M個の縦棒がありN個の丸で区切る。i個目の丸の左にある棒の総数がa_i。丸で区切られた棒の塊がN+1個あり、それぞれの個数をmod 3で固定してその分を最初に配る。すると、残った棒の数が3の倍数である必要があり、3個ずつ配るのが何通りあるかは前計算しておけばO(1)でわかる。mod 3で固定する側も、端の2箇所は3*3通り全部試すとして、それ以外のN-1個の塊が1か2になるので何個2になるかを固定すればO(1)で何通りあるかわかる。なんか思ったより普通に解けるんだな。3の小ささを使うというのがポイントか。解説を見ながら悩んでる時間無駄なのでどうにかしたい(あの時間は何も考えていない)。