ABC288

ABCEFの5完。Cまでは実装軽くて好き。D以降は難易度の高さに面食らったけどまあ力があれば楽しめそう。

A - Many A+B Problems

簡単でいいね。

B - Qualification Contest

難しそうに見えて、最初のK個だけ受け取ってソートすればいい(名前の辞書順に順位を出力しろとかかと恐れた)。

C - Don’t be cycle

解法を未証明なうちから、連結成分の個数が必要そうだと思っていたが、実装していくと、単にUnionFindでmergeされなかった回数でいいと気づいた。簡単そうだと思ったのにけっこう手間取ってしまった。

D - Range Add Query

なんか累積和みたいのを前計算しておくんだろうなとすぐ思うが、具体的な形がびっくりするくらい見えない。とりあえず愚直(端から合わせていくやつ)を書いてみるが、それを元に高速化とかもできない。将棋で手が見えないときみたいな感じで何もできない。飛ばした。

EFを通して戻ってきた。実験で一つの要素の寄与を見てみる。どうにかこうにかエスパーしていくと、終了後15分くらいして通った。それを元に考えると、確かに必要十分条件になっている。1 1 1 0 と 0 -1 -1 -1 を重ねることで 1 0 0 -1 が作れる、つまりmod Kで同じ場所へ自由に渡せるというのがポイントだった。

E - Wish List

DPっぽいけどかなり要求値が高い。0-indexedで考える。イメージとしては、Cを固定してAからだるま落としみたいに買っていく(そのときに同じ位置の追加料金を払う)。まず、番号がiの商品を買うとき、番号がi未満の商品(i個ある)をj個買うなら、Cの中でi-jからiまでの好きなものを使える(番号が小さい商品から買っていって、ちょうどいい位置に来たタイミングで買う(うまく説明できないな))。そうすると、番号iの商品まで見てj個買ったときの最小値でDPできそう。問題はCの最小値だが、買った個数jが増えるたびに選択肢が増えていくので適切な向きに最小値を更新しながらやればいい。商品iを買う/買わないの2通りの遷移があるが、買うことが確定している商品は買う遷移だけする。

まあ俺もね、DP苦手とは言っても、このくらいはできるんですよ。

F - Integer Division

ある場所で区切ると仮定すると、左側の区間の答えと右側の区間の答えがわかっていればその積が答えになりそう。ただ、もちろんそこで区切らない場合も考える必要がある。左から1個ずつ区間を伸ばしていってという方針、自分はこういう問題でよく考えるけどあまりうまくいかないイメージもある。でもまあそれをやる。1個足すとき、そこで区切るなら簡単。区切らないとき、直前の(最も右にある)区切りがどこかで場合分けすれば2乗で解けそう。これをまとめて処理したい。なんか10倍して足してっていう感じだけど、なかなかうまくいかない。それっぽくやってもサンプルが微妙に合わない。

かなり時間をかけた。サンプル1の具体例で考えてどうにか辿り着いた。そもそも、直前の区切りの位置毎に何通りあるか考えると、「4 2 1 1 で8通り」みたいになる。最後の1は、区切りがない場合(なるほどねー)。便宜上、最初の数字の左側で区切ってその左には1があると思っておく。左から短い区間の答えを求めていくが、その答えの累積和みたいなものを持ちたい。で、直前の区切りの右側は1個の数。これをまとめてやる。10倍して下の位を足すとき、相手がたくさんいて、ここで累積和がはまる。答えの累積和には最初の1も足しておくというのがポイント。単純なコードになるねー。理解度は低いけど、こういうのをねじ通すの好き。