ABC256

何もできなかった。EFGを並列に考えていたが何もわからん。順位表を見てEだけはねじ通した。

A - 2^N

シフト。

B - Batters

後ろから残塁を求める方針もちらつくが、素直にやる。途中で、ビットで管理すると進塁がシフトで済むから楽だと気づきそうする。popcountではみ出したのを数えたけど、そんなことせずこれこそ残塁を調べればよかったか。

C - Filling 3x3 array

1を引いて、非負整数を書き込むことにする。すると和は最大で27なので、そこに仕切りを2個入れて1行で406通り。それを3行決めて406^3通りを全探索はちょっと実行時間が不安。いくつ決めれば全部決まるか考えてみると、例えば左上の4つだ。これを27^4通り調べるのは間に合う。残りを引き算で決めて、右下隅だけはもう片方の和が合ってるかを確認。最後に、全体で負の数がないかチェック。楽な書き方あったかなあ。

D - Union of Interval

お、これは典型。存在は認識して未履修なので、俺にできるかなとドキドキする。Lでソートしてみる。左から見ていくと、次のやつと離れてるなら今の区間は他のどの区間ともくっつかない。そうでないとき、次の区間とくっつけてもソートされた状況に変わりがない。区間が決まったらその都度出力していく。最後に今の区間を出力して終わり。意外と簡単だった。

(解説を見て)なんでLRが小さいんだろうと思ってたらいもす法が使えるのか!

E - Takahashi's Anguish

ソートするのかなとか。ループしたら少なくとも1個はコストがかかるけど他の人との兼ね合いで2個になることもあるのかなとか。捉えどころがない。

連結成分毎に考えると、頂点数と辺数が同じ。つまりループを一つだけ含む。ループに注目すると、その中で最小のコストは払う必要がある。ループに含まれない部分は前に持ってくれば(先にキャンディを渡せば)コスト0。他の連結成分とは干渉しないので、そのコストが達成できる。実装が難しくて、とりあえず今回やったのは、各頂点から辺を辿っていき訪問済みに当たったら改めてそこから辿ってループを検出する(ループ内のC_iの最小値を答えの変数に足す)。しかし、訪問済みに当たったときそれが本当にループかはわからないと途中で気づいたので、最初の頂点番号を探索の世代として訪問済みフラグとは別に持ち、今の探索で訪問済みになった場所ならループ、そうでなければそこにループはないと判断した。

F - Cumulative Cumulative Cumulative Sum

A_iが変動したときのDへの寄与を考えると、D_iに1倍、D_(i+1)に2倍というふうにD_Nまで続いていく。これも捉えどころがなくて困っていたが、まあ遅延セグ木に乗る気もしてきて。クエリxに対しては先頭からxまでの和を返す。足すときは、xから最後まで(増分に1, 2, 3,...を掛けて足す)。コンテスト終了後に提出したがWA。

(追記)方針自体は何回考えても正しい。めちゃくちゃ苦しんだが、手元で撃墜ケースを作るという面倒な作業をやってデバッグできた。等差数列を足し込むときに、左端に足す値と右端に足す値を持つようにしていたが、端の具体的な位置ってどこよとなるので遅延セグ木のpropagate部分を手でいじって対応しており、しかしそこだけではなく再帰的に木を下りる部分でも対応する必要があったのではないかと気づいた。そこは対応せず、セグ木のノードに位置を持たせ、足す等差数列は位置0での値と公差を持つようにした。これでようやくAC。

G - Black and White Stones

各辺で等しいという白石の個数を固定すると、頂点に白石があると隣の2辺で白石が1個ずつ減る。各辺1個のときは特殊で連続した頂点に置けなくなるがこれだけでもけっこう難しそう。DPっぽくはあるけどなあ。

(追記)DPっぽいのは気づいてた、とはいえやっぱり不可能な問題ってDPなんだな。辺上の白石の個数を固定する。辺をぐるっと見ていくことにして、各辺について前の頂点と後の頂点に白石を置くか場合分けすると、頂点を除くD-1個の石のうち何個白石を置くか決まってこれは簡単。遷移を2*2行列で表しそのN乗を計算しておけば、あとは最初の頂点が白石のときとそうでないときのベクトルを作ってその行列を掛ければ最後(最初と同じ場所)が白石かどうか合う通り数が求まってそれを足していけば答え。けっこうシンプルなコードになるのな。