ABC267

ACDEの4完。Bが本当に嫌いなので飛ばした。Fがわからないのは頭が残念。

A - Saturday

これいちいちクオートするのが面倒というか人間のする仕事じゃないんよな。変換するツールを用意しておくべきか。ただまあこれは出題するほうが悪い気もするのでわざわざ用意するのもしゃく。必要なツールならいくらでも時間かけて用意するんだけど(それも楽しいプログラミングなので)。

で、stringの配列にしたら何番目と一致するか検出して出力。ついつい、Mondayのインデックスが1だと思い込んでしまったが当然サンプルは合わない。SundayがないのでMondayのインデックスは0だった。2分は切りたかったなあ。

B - Split?

ピンの配置を手入力する必要がある。人間がしていい仕事ではない。「ピンが全て倒れている列が存在する」の実装が重すぎる。10分くらいしたところで、コンテスト中にやっていい時間の使い方じゃないと気づき、飛ばした。

実は、「立っているピンが 1 本以上存在する」の否定が「ピンが全て倒れている」だった。このことに気づけなかったのが敗因。だから、レーティングが下がることに文句はない。ただ、このB問題のせいで100分中10分を浪費し、そのうえ最悪な気分でC以降をやることになった(普通なら楽しく解いてるはず)。本当にこのB問題が嫌いだ。

(追記)B問題をupsolveって面白いな(?)。「一つでも立っている」を前計算しておき、3重ループ。思ったよりは短く書ける。

C - Index × A(Continuous ver.)

難しそうだが、長さMの連続部分列はO(N)個しかなくてしかも差分計算できるので解けた。最初(A_1からA_Mまで)のを計算したら、それを仮の答えとして最大値を更新していく(答えは負になりうるので初期値の設定が面倒だったがこれで解決するしこの後の更新回数もN-M回なのでfor文が書きやすい)。その区間の累積和を引いて次のM*A_iを足す。累積和もA_iを足してA_(i-M)を引くことで更新していく。

D - Index × A(Not Continuous ver.)

Cとの関係に気づくのけっこう時間かかった。こっちのが難しいのかーと思いながらソートしたが、ソートしてはいけなかった(順番が関係ある)。DPですね。最初のi個からk個を選んだときの最大でまとめることができる。DPテーブルは全部-INFで初期化しておいて、0個から0個を選んだところだけ0にする。わざわざDPテーブルを初期化したのは配るDPにするため。遷移の図を描くとわかるけど、これは配る形をしている(実装が楽)。k個からk+1個に増えるときはA_i*(k+1)を足す。特に定数倍高速化はせずDPテーブルを三角形に全部埋めてdp[n][m]を出力。

E - Erasing Vertices 2

「辺で直接結ばれて」を見て「直接辺で結ばれて」ではないから「辺で結ばれて」だなと誤読して、どっちだろうと思いながら何回もサンプル含め読んでいたら「直接」を見つけた。正しい読みがわかっても、不自然な設定に思えて捉えにくかった。操作全体のコストもわかりにくい。和で計算しないコストってあるのか?

まず二分探索を思いつく。実行時間制限も4秒だしlogを2つ付けて大丈夫。コストの最大値がXでできるか判定するのは、X以下のを操作してしまっていいのでpriority_queueで小さい順にってところで二分探索いらないじゃんと気づく。改めて正当性を考えると、答えは今できる操作のどれか以上になるし操作をすることで他の頂点に対する操作のコストは悪化しない。よって最もコストが小さい操作をしてしまってよい。証明できたので実装。まず全部の頂点のコストを計算して頂点番号とともにpriority_queueへ入れる。頂点iを削除するときは隣の頂点のコストからA_iを引いてpriority_queueに入れなおす。ダイクストラ法みたいだ。削除済みかのフラグも持ち、削除済みだったらcontinue。現在のコストを持つためのvectorも用意する。頂点iを削除するためのコストも計算していたが、これは単にpriority_queueに入れたコストを使えばよかった(一致するはず)。提出してWA。

考察と実装を全部見直してどこも間違っているとは思えないのでFへ(8分程度使った)。わりとFに集中できた。残り時間が少なくなりFを通す見込みがなくなって戻ってきたが、N回操作してるつもりがcontinueしたのも回数に含めてた。今度はAC。提出時刻は遅くなったが、Fを考える時間はそれほどロスしていないのでよし。

解説見たけど、これ二分探索できる人なら二分探索しないだろ。ただ、X以下かで分ければいいのでpriority_queueが不要となりlogは1つで済むんだな。これは気づかなかった。

二分探索の上限を考えているときに思ったけど、答えはどこまで大きいのが構成可能なんだろうね(けっこう小さい気がしてた)。スターグラフだと端からやれば小さいし、完全グラフはNが小さくなる。

F - Exactly K Steps

解きたくなる見た目をしている。DFSしながらスタックで履歴を持ってとか考えてたけど、祖先や子孫はいいとしてそれ以外がきついんだよね。1個でもあればいいので子孫が深い順に探索して一番深いやつだけは2番目を相手にしてとかを探ってたけど枝分かれが多くて厳しい。ただ、めっちゃ深いやつは少ないので可能性はありそう(解ける問題ではありそう)な気はしていた。

いや直径は全く思いつかなかった。深い順に探索とか、雰囲気はそうだったのに。本当に頭が固い。

(追記)よくわからんけど直径となる2頂点のどちらかがどの頂点から見ても最遠の一つになっていそう。各頂点にクエリのvectorを持たせ、祖先たちをスタックで管理するDFSをしながら処理していく。それを直径の端2頂点からそれぞれやる。答えは-1で初期化しておき見つけたら上書きしていけばいい。

Gは読んだだけ。