ABC306

6完。今更きりみんちゃんをフォローした。

A - Echo

答えのstringを用意して書こうとして、単に1文字ずつ処理する(2回出力する)のでいいと気づいてそうした。1分切れると嬉しい。

B - Base 2

llをullに書き換える。上の桁から与えられるなら2倍して足してでいいけど、逆なので(0-indexedで)i番目はiだけシフトする。

C - Centers

それまでに現れた個数を管理しながら、真ん中なら出力していけばいい。f(i)の昇順というのが、与えられた数列内でも真ん中のやつは同じ順番になっているという気づき。

D - Poisonous Full-Course

難しそうだけどDPできる。毒入りかどうかで場合分け。書いてるときは気づかなかったが、2*2=4通りの遷移があるのでそれを振り分ける(死ぬときは虚空に捨てた)(こういうのが最初から見えると見通しよくなる)。

E - Best Performances

multisetを2本使うやつ。priority_queueでできるか考える時間はない。multisetを使っても実装は重い。制約から、multisetの小さい値が入るほうは空になる可能性があり、大きいほうは空にならないという性質がある。まず、削除する値がどちらに入っているかを判定して削除、ついでにそこへ新しい値を入れてしまう。次に、小さいほうが空でなく入れ替わりが生じてるなら入れ替える。大きい側の和の管理もしておく。何度も書きたくないし、ライブラリ化するかなあ。しかしどう作るのか(どういう仕様なら競プロで使えるのか難しい)。

F - Merge Sets

答えはO(N^4)。愚直の計算量はO(N^2*M*log(M))。難しい。しばらく考えて、A_i,j一つの寄与を考えることを思いついた。全体をソートして二分探索で求める。しかし、f(A, B)とf(B, A)は異なるし足したらつまらない値になるから全体をソートしたのではだめで、M個ずつ追加していかないといけない。が、N回もソートする時間はない。いや、値がN*M未満の非負整数なら?これはセグ木に乗る。座標圧縮すればいい。おもしれえ!1からMまでの和はベースで足されるとして、他は単にBITするだけ。

ジャッジにめちゃくちゃ時間かかったがACでよかった。

G - Return to 1

簡単そうだと思って順位表見てびっくり。たしかに難しい。

5の倍数ならいいかというと、長さ3万の閉路があってもそれだけではできない。長さ7万のもあれば可能になってしまう。素因数に2と5しか含まれない長さの閉路があれば?しかし閉路の全列挙はできない。そういう長さが1個でも存在するかが重要だがこれも位置による。存在しないときはどう検出するか、またどう判定するか。

あー、頂点1を含む閉路だけ考えればいいの気づかないなあ。