目次

AtCoder Beginner Contest 241(Sponsored by Panasonic)D,G問題メモ

AtCoder Beginner Contest 241(Sponsored by Panasonic)

D - Sequence Query

D - Sequence Query

問題

解法

$k$ が小さいので、例えばクエリ2なら「$x$ 以下で最大の値 $y$ と個数を得る」 「$y-1$ 以下で最大の値 $z$ と個数を得る」……で $k$ 個に達したらそれが答えとなる。

C++なら、multisetを使えばほぼそのままの関数が用意されているんだけど、 毎度のことながらPythonでは平衡二分探索木がないので、自分で代わりのものを実装する必要がある。

どうやるのが速いんだろうね。Python3でACが早い方から見ていくに、

みたいな感じだった。
まぁ、この辺を把握しておくとよさそう。

また、Binary Indexed Tree や Binary Trie も、 素の状態ではなく、multisetに相当する関数を用意した状態で準備しておくと混乱せず使える。

個数が $k$ に満たないとき用に、番兵として -1 と INF を5個ずつ入れておくと楽。

Python3

G - Round Robin

G - Round Robin

問題

解法

それぞれの人について独立に判定する。

人 $i$ が単独優勝できるか?
可能性の話なので、残り試合は全て勝つものとして問題ない。

よって、「終了した試合での勝ち数」+「残り試合数」が $i$ の最終的な勝利数 $V_i$ で、 他の人はこれ以上にさせないことができるか?という問題となる。

基本的には、$V_i$ が、他の人の現時点での最大勝利数より大きければよさそうに見える(多く勝ってる人には今後負け続けてもらう)が、 たとえば以下のような場合(AND条件)は、$i$ は単独優勝し得ない。

終了した試合での勝ち数が多い人は残り試合でなるべく負けてほしいが、 そういう人同士の対戦ではどうしてもどちらかが勝ってしまう。
2人だけならいいが、複数人が絡んできて、またその残り試合も誰と誰は終わった、残っている、がバラバラなので どこから決めれば最適か、一概に決めづらい。

このような問題は、最大流に言い換えられる。

$V_i$ が決まった段階で、それ以外の人につき、「あと何勝まではできる」というのが決まる。

この時点で、$i$ 以外に $V_i$ 以上勝っている人がいれば、$i$ は単独優勝不可能。

それ以外の場合、 「始点 → 人を表す $N$ 頂点 → 残り試合を表す頂点 → 終点」というグラフを作る。($i$ が勝利すると決めた残り試合は除く)

を張り、残り試合数分だけの容量を流せれば、$i$ 以外の全員を $V_i$ 未満の勝利数に抑えられる試合結果が存在することになる。

グラフの辺の容量は人によって変化するものの、頂点間の辺の張り方・構造は不変のため、 毎回グラフを作るより、リセット・容量の変更を可能にしておくと、若干速い。

Python3