ABC364

6完。淡々と。

A - Glutton Takahashi

オーバーキルではあるが、sweetが何連続で来ているかを持って、2連続になったらそこでbreak。食べたのがN個かどうかで判定。A問題は実装がどうしても愚直寄りになる。2分35秒はかかりすぎかなあ。問題が複雑すぎるから仕方ないよ。

解説のやり方はシンプルだけど、そこまで深い考察をする時間はない。それでも考えたほうがいいのかなあ。

B - Grid Walk

これはやるだけ。やりたくねーって言いながらしぶしぶ実装した。

C - Minimum Glutton

甘さしょっぱさどちらに引っかかったかを両方試す。求めるのが最小値なので実は簡単という。ABを別々にソートしていいのが面白いし、そこがこの問題の難しさだと思った。

D - K-th Nearest

Aが固定なのでまだ簡単そう。B_jから両側を見るのは難しそうだが、少しして二分探索を思いつく。距離dの範囲にあるAの要素が何個かは、境界に気をつけて二分探索で求まり、それが初めてk_j以上になるdを二分探索で求める。logが2個付くから10^5で3秒なのね。

(追記)近いk_j個はA上で区間になる。区間の位置を二分探索できそうなのでやった。区間の左端と右端のB_jからの距離を比較して右端のが遠ければ右へ移動したくなる。初めて左端のが遠くなった場所を見つけてその一つ前も(存在すれば)候補なので比較してというのを提出。普通にlogが1個で解けるのな。コンテスト中は見慣れた形に飛びつくしかないけど。さて、他の(logが1個の)提出を見ると、自分のと違ってシンプルなコードばかり。自分より1離れたもの同士を比較していた。ステージが上の考え方だ。かなり難しい。長さが1短い区間を考えて、左右どちらを付け加えたいかを見る。初めて右のが遠くなったら左のを付け加えてそれがそのまま答え。正しく動く証明はできそうだけど、イメージがよくわかってない。コードが自然なので正しそうに見えはするが。ABCは勉強になるなあ。

E - Maximum Glutton

一見してDPだが、制約からそう思っただけなのでちゃんと考える必要がある。考えるとやはりDPで行けそう。メモリは使い回すにしても2次元配列なので、最後に答えを求めるところがめんどくさそう。そこで、dp[k][j]を「k個選んでAの和がちょうどjのときのBの和の最小値」ではなく「k個選んでAの和がj以下のときのBの和の最小値」とした(各kに対しdp[k][X]だけ見ればよくなる)(実装の変更点はdp[0][*]を全部0にするだけ)(この辺は実装しながらすり合わせていく)。in-placeで行けそうな気もしたが、実装時間を短くするためにそのまま。Bの和がYを超えない最大のkを見つけて、これが「それ以降の料理は食べない」状態にならず食べれる最大数なので、問題の答えとなる最大を達成したとき最後の料理を食べる前は「それ以降の料理は食べない」状態になっていないことから、そこに1を足せば答え。ただし、XもYも超えずにN個食べれた場合はもう料理がないので+1しない。

(追記)forを逆順にしたらin-placeでできた。in-placeにできるならしたほうが考えることが減る面もある(コンテスト中はコピー先の配列の初期化(dpをpにコピー)が必要なのをうっかりした)。

F - Range Connect MST

まず、連結かを考える。頂点1からNまでが連結になればよい。std::setを使うやつとか考えるが、遅延セグ木ならできそうだと思いそちらへ。演算構築に時間がかかる遅延セグ木は避けたいのでセグ木でできないか考えると、できそう。二分探索するのでACLを使う。辺追加の順番は関係ないので、コストの昇順にソートしておく。あとはクラスカル法をやるだけ。最初のころ実装がめんどくさそうだなあという予感がしていたが、実際はそんなことなかった。頂点番号N以下の部分に関しては連結成分が区間になっていることを使う。区間の最初に1を置き他は0。まずL_iへ辺を張る。セグ木の演算は和とし、L_iのいっこ右から見て最初の1を二分探索で見つける。次はそこへ辺を張る(単にクラスカル法をやっている)。全部連結になっても最初の1本は辺を追加する(全部連結になったかをフラグで管理してたけど、今考えると必要なかったな)。

(追記)コンテスト中のコードは冗長だった。L_jを次の区間の開始位置へ更新していく感じで書ける。setを使う場合は番兵を置くと多少楽だが、全部連結になった判定のst.size()が1ではなく2になったりしてsetの煩雑さは残る。

(追記)なんとUnionFindでできる。連結成分の中で最も大きい頂点番号をUnionFindの中で持っておく。連結成分が区間になっているとこんなことまでできる。