ABC242

5完。1900割るとは思ってなかったなあ。この前のABCと同じく、簡単だけど脳破壊実装な問題(今回でいうとE)にやられている。Fはコンテスト中にちらっとしか見なかったが、やっていても間に合わなかった。Gはまだ解けていない(クソ重くて遅そうな解法は思いついてる)。Dに時間がかかるのが力のなさ。体の調子も思うようでないし、ずっと気分は沈んだまま、何もできずに過ごしている。

A - T-shirt

難しすぎる。俺が3分かかるって。入力が4個もあるわりに1000は与えられない(結局使わない)。A位までにA人、B位までにB人というのが見抜ければ早解きできたかもしれない。自分にとっては簡単な内容だが、それを確実に読み取るには時間がかかる問題文で、そういうのをAに出してほしくない。

B - Minimize Ordering

ソートするだけなので逆に時間をかけて確認したくなる。

C - 1111gal password

何で終わるのが何通りあるかでDP。簡単だとは思うけど時間はかかっている。何が足りないのか。

D - ABC Transform

めちゃくちゃ難しい。まず、tが60以上のときは(kが2^60未満であることから)Sの最初の文字由来の場所を出力することになる。そうでないときはtが小さいので普通にtだけシフトすることができて、何文字目の何番目を答えればいいかわかる。また、ABCを012とmod 3の数に置き換えて考えると、変換前の数が+1されるとt回の変換後の数もそれぞれ+1される。よって、0から始めてt回変換してk番目が何になるかわかればよい。20分くらい考えてここまでで止まっていたので一旦飛ばした。

例えば3回変換したものは01121220となっており、後半は前半をそれぞれ+1したものとなっている(定義に戻れば納得できる)。つまり、kが後半を指していたとき、前半を見て1を足せばいい。この操作はO(log(k))回でいいけど、tがでかいのでそちらも考える必要がある。何回も変換したときの先頭の数は0,1,2,0,1,2という明らかな規則性がある。ここまでの処理によってkは2^t未満である保証があるので、kが0になるまで操作してから残りのtをやればいいというか、これコンテスト中はよくわかってなかったけど、ここでわかるのはt回操作後の先頭の文字との関係であってその文字は単にt%3でわかる。

最初にやったtが60未満のときの処理とのつなぎがわからなくなってたりしたけど、改めて考えてつながりどうにか解けた。kを減らす操作がやけに単純で気持ちの整理がつかなかったけど、今考えるとこれは単にkのpopcountのmod 3だ。文字列"0"に対してt回操作して先頭が0のとき、k番目(k<2^t, 0-indexed)の文字はpopcount(k)%3になっている。0を01に、1を12に、2を20に変換することとすれば、これは2倍して0を足すのと1を足すのになっている(桁数を1ずつ増やしながらちゃんとビット数を数えている)。

E - (∀x∀)

Nが偶数と奇数で場合分けが生じそうで嫌になる。'A'を引いておき26進法で扱う。考察時は普通に10進整数でやればいい。先頭半分だけ見て、Sより小さければよい。その個数は普通に整数を先頭からパースするだけ。Sと同じときは、Sの前半と後半を比較して同じであれば+1。大きくても+1だし、小さければ何もしない。

回文の自由度と比較のスタート地点2つと比較する個数でN/2に近い整数が4種類も必要になった。そんなに多くなるわけないという思い込みからか勘違いをしていてサンプルが通らなかった。ここは珍しくサンプルが親切で助かったが、いずれにせよ時間はかかる。そんなに難しくないのに30分持ってかれるのはつらい。Sの前半と後半の比較はもっと楽な方法があったのだが、どうすればそちらに行けたのか。

F - Black and White Rooks

コンテスト後にTwitterを見ないで考えた。わりと素直に解ける。なんかめちゃくちゃ時間かかったけど。普通に時間かかるのに加え、最後包除で符号を計算しておきながら掛け忘れてて時間かかった。

黒と白は同じ行・列にない。何もない行や列の個数を固定することを考える。4乗が通る制約なので、4重ループを考える。空き行と空き列の個数を固定すると、どこを空きにするかでコンビネーションが掛かる。その中身は、黒が何行何列使うか固定して足し上げる。黒と白の、どの行どの列にも駒があるパターンが決まれば、どう混ぜるかはさっきと同様のコンビネーションで、部屋のサイズが決まってるときの各色の通り数は、4重ループ内では無理だがパターンが少ないので前計算すればいい。この前計算が本番だ。駒の個数は2種類しかないので思ったより楽。縦横両方あってややこしい。まず、どの行にも駒がある通り数を求めて、それを使ってどの行にもどの列にも駒がある通り数を求める。3重ループ2回で済む。実装は、長いけどいつものやつ。難しいのは、同じものを2回以上カウントしていないと確信すること。

G - Range Pairing Query

順位表を見て残り20分はこれをやっていた。種類数がわかればいいと勘違いしてググって実装していた。

(追記)解説を理解する気力がなかったので自分で考えた方法でAC。平方分割。計算量は、O(N*sqrt(N)*log(N)+Q*(log(Q)+sqrt(N)))。logは付いているがbitsetで高速化できるのでわりと速い。区間内に奇数個ある色がいくつかわかればよい(区間の長さからそれを引いて2で割れば答え)。出現回数が多いやつ1000個はbitsetで累積和(mod 2でわかればいいので累積xor)。それ以外のやつは100回未満しか出現しないので、クエリをrでソートし、クエリを処理する前にrの位置までBITを更新する。BITで区間内に奇数個ある色がいくつあるかわかるようにしておく。rから左を見て、各色について最初に現れた場所で+1、次が-1と交互になるようにすればいい。毎回高々100箇所を更新(2や-2を足して符号反転)すればよい。