目次

AtCoder Beginner Contest 237 E,G問題メモ

AtCoder Beginner Contest 237

E - Skiing

E - Skiing

問題

解法

ポテンシャルという概念の教育的問題。

満足度を正負逆転させて「コスト」とすると、最短経路問題となる。
しかし負辺を含むので、Dijkstraでは一部の意地悪なケースで計算量が増大し、 $O(2^{\frac{N}{3}})$ かかるケースが作れてしまう。

Bellman-Fordは負閉路さえ含まなければOKだが、そもそも計算量が $O(NM)$ かかる。

以下のように考える。

基本的に各頂点へのコストは、下り道しか通らなければどんな経路でも始点と終点の標高差となる。

しかし途中で登り道を通ると、2点間の標高差を $d$ として、$d$ だけ余分にかかる。
(本来のコストは $2d$ だが、そのうち $d$ は後でまた下るときに回収されるので、追加分だけを考えると $d$ となる)

この「追加分」だけを考えれば負辺は出てこないので、Dijkstraで「各頂点に到達するのに必要な最小の追加分」を求め、 それに $H_1$ からの標高差を加味することで、最小コストが求められる。

ポテンシャル

一般に、グラフでは以下のようにすると辺のコストを変換できる。

ここで、変換後の辺が非負になるよう上手く $p_i$ を決めるには、以下の条件が満たされればよい。

結局、これを上手く求めるのが難しく、一番シンプルと思われるものが「どっかの頂点からの最短距離」となる。

最短経路探索を高速化したいのに、どっちみち最初に最短経路求めなあかんのかい!となる。
世の中そんなうまい話はなかった。

だが、以下のような場合に有効活用できる。

2番目は、最小費用流を求めるときなんかに使われる。

今回は1番に当てはまり、$H_i$ を $p_i$ として使うことで、上式が全ての辺で成り立つことがわかる。

Python3

G - Range Sort Query

G - Range Sort Query

問題

解法

なるほどーと唸る上手い解法。
ソート結果全てではなくて、特定の1つの値の位置がわかればいいところがミソ。

ソートって基本的に計算量が大変だけど、シンプルにできる場合が1つある。
それは、要素が $0,1$ のみからなる場合。

これも愚直にやったら間に合わないが、区間更新・区間和の取得ができればよいので、 遅延評価セグメント木を使えば1回あたり $O(\log{N})$ で効率的に行える。

順列 $P$ を「$X$ 以上なら1、未満なら0」「$X$ より大きいなら1、以下なら0」とした2つの数列に変換すると、 2つはちょうど、$X$ の位置だけが異なった状態となり、その性質はソートしても変わらない。

この2つで個別にクエリを処理し、結果から異なる位置を探せばよい。

Python3

全ソート結果

特定の1つに絞らなくても、実装は複雑になるが、Binary Trieでsplitとmergeを繰り返すことで $O((N+Q) \log{N})$ で可能らしい。