ブログ名

競技プログラミングやお歌のお話をする高菜です。

Educational Codeforces Round 80 (Rated for Div. 2) 解法

コンテストページ

Dashboard - Educational Codeforces Round 80 (Rated for Div. 2) - Codeforces

解法

✔A - Deadline

条件は、d <= (x - n) * (1 - x) と書けて、右辺を x に関する二次関数と思うと、最小値がわかります。

✔B - Yet Another Meme Problem

条件は、B が 99999... の形であることと同値です。

✔C - Two Arrays

cat(A, reverse(B)) が弱単調増加であることと同値なので、隣接差を考えると二項係数になります。

✔D - Minimax Problem

数列 b は、数列 a[i] と a[j] の項ごとの max であるとありますが、こちらは最大化する問題ですから、好きに選んで良いとしてよいです。 そこで、a[i] の方で使う添字の集合を全探索です。

✔E - Messenger Simulator

時刻をキーとして、その時刻に受け取ったメッセージがその送信者にとって最新であるときに bit が立っている状態のものを考えましょう。すると、新しくメッセージを受信するたびに、その人が履歴のどれだけ深いところにいるのかが、前回受け取ってから今までの時刻でいくつ bit が立っているかでわかります。これは、セグメント木で処理可能なクエリです。また、各人最後のメッセージがいつであったかは配列で管理しておきましょう。

すると答えになりうるのは、初め、受信直前、受信直後、最後ですから、これらのタイミングで答えを更新していきましょう。

✖F - Red-Blue Graph

考えたこと

次のようにフローに対応させると、湧き出し・吸い込みの条件付きの最小費用循環流問題になります。

    • 上側の赤い頂点は 1 以上の湧き出しです。
    • 下側の赤い頂点は 1 以上の吸い込みです。
    • 辺を赤く塗るのは、下向きに 1 のフローを流すことです。
    • 下向きの辺は容量が 1、コストが r です。
    • 上側の青い頂点は 1 以上の吸い込みです。
    • 下側の青い頂点は 1 以上の湧き出しです。
    • 辺を青く塗るのは、上向きに 1 のフローを流すことです。
    • 上向きの辺は容量が 1、コストが b です。
  • 白い辺

    • 白い頂点は太っ腹なので、いくら湧き出しても吸い込んでも起こりません。

さらに、ソース s とシンク t を用意して、次のように変換すると、湧き出しと吸い込みのない、最小流量付き最小費用流になります。

  • s から湧き出し頂点に、最小流量 1 の無料辺を張ります。
  • 吸い込み頂点から t に、最小流量 1 の無料辺を張ります
  • 白い頂点に関しては、s からと t へと、両方とも容量無限の無料辺を張ります。

さらに、最小流量付きの辺は、頂点を倍加することで制約なしの問題に帰着できます。

  • 湧き出し頂点 x について、それを倍加して x' を爆誕させて、容量無限の無料辺 s -> x -> x' を張りさらに x->x', x->t に容量 1 の無料辺を張ります。
  • 吸い込み頂点 y について、それを倍加して y' を爆誕させて、容量無限の無料辺 y' -> y -> t を張りさらに y'->y, s->y に容量 1 の無料辺を張ります。

最小費用流は、増分路のうちコストが最小なものを Bellman -- Ford のアルゴリズムで探して、そこにできるだけ流すを繰り返すとよいです。

ダメだったこと

これは、どうなのでしょうという気持ちはありつつ、よくわからないので見てみぬふりをしていたのですが、そうです。フローを流す順番は操作できます。こちらのブログが参考になります。これをすると通るはずですから、後日実装をしてみましょう。

snuke.hatenablog.com

結果

f:id:ngtkana:20200115024843p:plain

77 位です。良い方なのではないでしょうか。