ARC168

3完。一応黄パフォだけど、だいぶ時間かかっちゃった。時間がかかったのも順当としか思えないのがな。

A - <Inversion>

単に数列と言ったときは、実数の列を指すのか?複素数を含まないことを読み取れなかった(大小を論じてるから含まないとは思うけど)ので、逆に整数に限るんじゃないかみたいな心配も(ないけど)出てきて、まあ実数で考えることに。また、サンプルを見ると等しい数のペアは転倒にカウントされない。

転倒数が小さくなるように点をプロットしていくと、上がるときは大きく、下がるときは小さくという感じになる。ここで、'>'が連続するところを考えると、どうやってもそこは転倒してしまう(協議単調減少なので)。そして、そこ以外に転倒が生じないようにできる。ということで、下がってるときに何連続で下がってるかを足していけばよい。

B - Arbitrary Nim

k個以下という制限を付けたNimのGrundy数がわかるかなと心配したけど、ググって答えを見てみれば当たり前というか、小学生のときに流行った30(31だっけ?)を言ったら負けのゲームが、k=3のケースだ。mod k+1で総xorが非0になればよい。まず外堀を埋める。総xorが最初から0なら、十分大きいkは全部Aliceの勝ちになるから、-1を出力。そうでないとき、サンプル3のようなケースはmodをどう設定しても変わらないので0を出力、しかしちゃんとした条件はまだわからない。そうでないときは、どうmodを設定したら総xorが変化するかという話になる(ここが本体)。ソートして同じ数のペアとかやってたけど、一旦書き直す。最初Aliceが負けの場合、同じ数のペアを除けるだけ除いたものを考える。ソートして別のvectorに(括弧列の処理みたいに)入れる。末尾と同じならpop、そうでないならpushすればいい。これが空ならどうしようもない0を出力。そうでないなら、最大のものより大きいmodをとっても意味ないし、最大の数(ペアを除いたのでちょうど1個)でmodをとれば総xorが0からその数に変わるのでAliceの勝ちになる。これで解けているはずだが、最後に1だけが残ると0を出力することになるので、そういうことは起こらないと納得するのに少し時間がかかった。同じ数のペアしか取り除いていないので、総xorは変わらず0で、最大値が1の正整数の集合でそういうものは存在しない。

C - Swap Characters

CDを両方読んで、CがわかんなくてDを考えて順位表を見てDをちょっと考えてわからなくてCに行った。

与えられた文字列は各文字の個数だけが重要(自分はいつも重要という言葉を脳内で使ってるけどもっといい表現があるんじゃ?)で順番は関係ないということに、なかなか気づかなかった。S="ABCABC"などとして、色々な並べ替えについて何回で構成できるかを手で試していた。近いものに対応付けてというわけにもいかない。そのうちに、Sと違っている2箇所をswapして両方合うケースと、ABCをBCAにするような3箇所を2回のswapで合わせるケースがあることに気づく。ここで、「AがBになった個数」など9通りの個数を3*3の表に書くことを思いついた。考えていくと意外にも解につながっていそうな鉱脈だった。この表の4つを埋めると他も決まるので、K^4でなんとか間に合いそう。この表の条件を満たす全てのパターンについて、何通りあるかコンビネーションの掛け算で計算して足していけば答えになりそう。しかしここから実装とデバッグに時間がかかる。自由度が3に見えて4だったとか、冷静になる時間がなかった。3箇所を合わせるswap回数が3だと思ったり、その掛け算を別のところにしていたり。まあコードがこんなに長くなってる時点で実力不足なんだよな。解けそうとと思った後で実力差が出る。なんとか時間内にACできてよかった。

D - Maximize Update

最初Lでソートして左から見てわかんなかったけど、Cを通してから見てみると、(左から見るなら)Rでソートすればまあそれっぽい。Rが同じ中ではLの降順にして、なんかそれっぽいけど何を優先するか色々あって難しい。よくこんなシンプルでわからん問題作れるよな。

(追記)逆から見るのが前日のABCのEで出ていたのに全く違うものに見えていた。制約から区間DPは思ったけど、まさかその区間DPで解けるとは思いもしなかった。結局、最初から最後まで解説放送に頼ってAC。最適な方法で塗ったとき、最後に塗ったマスの一つをとると、それまでにそのマスを塗ってはいけないことから都合良く問題が2つに分割される。最後に塗ったマスを含み、その区間に含まれる区間が存在するかを判定する必要があり、これは2次元累積和でできる。思考が完全に区間スケジューリングになっていて、全く思いつかなかった。これで区間DPできそうだが、包除とか最後のマスを使わない単なる合併とかも考えてしまい混乱。通り数ではなく最大値を求めているので、網羅していれば重複があってもいい。最後に塗ったマスはその区間の答えが0でないかぎり存在するのでそのどれかをチェックすればいい。最後に塗ったのが端だった場合は、長さ0の区間を見ればよい。以前は区間の長さの昇順に区間DPをしていたが、今回考察の過程で普通にLRの2重forでいけると気づいてそうした。まずLの降順、内側でRの昇順。長さ0の区間は計算済みとして、Lが変化することで新しく現れた長さ1の区間をまず計算するように気をつける。