ARC180

1完。ゴミ。今回の出来がゴミというより、俺がゴミ。

A - ABA and BAB

大雑把に、ABABABのように、交互に連続しているものを消せる。端が気になるが、とりあえずABAの左のABを消しても右のBAを消しても結果は同じ。前から貪欲に消せるものを消すと、消せなかったAとBの塊が残る。その塊で区切られているため、消せる区間毎に何個消すかで数え上げができそうだ(どれを消すかは影響ない)。問題は、区間毎の個数が異なりかつ消した結果の文字列が同じになることがあるか。交互なので、奇数番目反転も考えたが、塊が残るのと比べてきれいに見えなかったので捨てた。塊は基本的に同じ文字が連続しており、それが消えないとなると消す区間の区別はできそうだ。ということで、前から見て現在の位置がABAかBABであるかを調べて、そうだったら1文字飛ばしてまた調べ、違ったらここまで何回連続そうだったかをvectorに突っ込む。k個あったら消すのが0個からk個のk+1通りなのでそれを掛けていく。

解説。そうか、消すのが偶数個(2個)だから、操作しても各文字の位置の偶奇は変わらないのか。これ自分でどこまで深く考えれば気づけたんだろう。結論のシンプルさと裏腹に、自分にとってはかなり遠い場所にあった。

B - Improve Inversions

かなり難しそうなので、手元で例を作ってひたすら観察する。6 ... 5 4 で2回操作する。4 1 5 2 3 で2回操作する。4 3 2 1 で操作が被らないように、できる。ランダムに入れ替えるのを大量に試し最大操作回数を得る実験プログラムを書く。離れていても、差が1であれば転倒数は1しか減らない。そういうものをやるとよさそう。考えているうちに、ルールベースでやるよりないという感触になり、転倒数を下げない操作を貪欲にやっていくものを書いてみる。これは簡単に撃墜されたので、離れているもの差が小さいものからを優先するようにすると、差が小さいのをより優先するようにしてサンプルの操作回数が合っている。提出して見ると、TLE。4乗だから当たり前。すっかり忘れていた。WAは出ていないので、のぞみがありそう。しかし、かなり難しい。Nが500なので、O(N^3)にはなるはずと思い考えるが、全然できない(離れているものという条件を外しても)。仕方ないのでlog付きを書く。0-indexedで(l, r)のrをKからN-1まで動かして、相手として使える位置のlをBIT(最大値とその位置)(先頭からの累積だけなのでセグ木までは要らない)の(lではなく)P_lの位置に追加していく。バグだらけで5分オーバーした。logを付けても826msで通った。結果だけでいうと最初からlog付きで書いていればよかったが、立ち回りとしてはよかったと思う。

解説。「疑似転倒数」は思いついていたが、まさかそんないい性質を持っているとは思いもしなくて、すぐ捨てた。解説を読んでも矛盾が見つけられない。どうしたらこれを正しいと思えるんだ。通常の転倒数とどこまで同じ性質を持っているかわからないんだよね。解説で使ってる範囲では同じなんだろうけど、コンテスト中であればそれを自分で見ないといけない。例えば、転倒してるペアをswapしたときに疑似転倒数は本当に1以上減るのかとか。定義を見ただけでは全くわからないよね。自分のACしたコードが正しいかはもちろんわからない。

C - Subsequence and Prefix Sum

読んだだけ。終了後考えたが、もう遅いので寝る。
(2時ごろこれ書いてたけど投稿するの忘れて寝ちゃった)