目次

AtCoder Beginner Contest 369 E,F,G問題メモ

AtCoder Beginner Contest 369

E - Sightseeing Tour

E - Sightseeing Tour

問題文

制約

解法

$N$ がそこそこ小さく、$K_i$ が特に小さい。

Froyd-Warshallで、以下を $O(N^3)$ で事前計算できる。

各クエリに付き、以下を全探索すればよい。

この2つが決まれば、「$1$→1本目に通る橋の始点→終点→2本目に通る橋の始点→終点→…→$N$」の距離を $Dists$ から求められる。 その中の最小値がクエリへの答えとなる。

全クエリの計算 $O(Q K! 2^{K} K)$ (※$K$ は $K_i$ の上限)は、制約値の代入でおよそ $5.76 \times 10^7$ となる。
制限時間が長いので、間に合う。

もちろん、bitDPをしてもよい。その方が計算量は少なく済む。

Python3

F - Gather Coins

F - Gather Coins

問題文

制約

解法

$H \times W$ が小さければ、よくある経路数え上げDPのようにできるが、今回は大きいのでTLEとなる。

ただ、$H \times W$ の配列を一度に持たなくても、1行毎に使い回せば最大枚数だけは求められる。

これは、DP配列をセグメント木で実装して、$(r,c)$ に置いてあるコインを拾う場合は

とすればよい。$(r,c)$ の小さい順に処理していけばよい。
最終的な $\max(\mathrm{DP_{枚数}})$ が答えとなる。

経路を復元するためには、ここに「コイン $i$ の直前には、どのコインを取ったか」の情報があればよい。

これで、最大値を得るために通過したコインをバックトレースできる。

Python3

G - As far as possible

G - As far as possible

問題文

制約

解法

青木君が $N$ 頂点全てを指定したときは、明らかにオイラーツアーの距離(=全辺の長さの2倍)である。

ここから、指定頂点を減らしていくことを考える。

頂点 $1$ および $1$ を根とした時に葉となる頂点以外は、指定から除外しても変わらない。 (結局、葉まで行かないといけないので)

さて、いよいよ葉のいずれかを指定から除外しなければいけなくなったとする。

    ①
  /  \        ○: 葉以外
 ②     ③      ●: 葉
 /\   /|\
❶④ ⑤ ❹ ⑥
  | |    /\
  ❷ ❸   ❺❻

この時、「最後の分岐から葉(自身)までの距離」が短い方から順に除外する、ということを繰り返すとよい。

❶❷にとっては最後の分岐は②、❸❹にとっては③、❺❻にとっては⑥となる。
葉を取り除くと、ゲームのスコアからは「分岐から葉までの距離の往復分」が引かれる。
なるべく青木君は引かれるスコアが小さい方から貪欲に除外していくのが適切である。(FIXME 本当に?)

ただし、各頂点にとっての “最後の分岐” は変化しうる。
例えば❺を取り除くと、❻は⑥で分岐しなくなり、“最後の分岐” がより根に近い③になる。
分岐する頂点 $v$ の子の中で最も選ばれるのが遅い子(=最も $v$ までの距離が遠い葉を持つ子)について、 このように最後の分岐までがより遠くなり、引かれるスコアが増加する。

以上を踏まえて、以下の木DPをすればよい。

子を複数持つ頂点では、「最も遠い葉を持つ子の値を親に引き継ぎ、残りの子の値は確定するのでDropに追加」という処理をする。

$f(v) := DP[v]+(vとvの親を結ぶ辺の距離)$ とする。

例えば⑥を処理する段階では、

のように遷移していく。③でも同様に、

このようにしていくとDropには、いずれかの葉を指定から除外したときに引かれるスコア(の半分)が蓄積される。

ソートして小さい方から除外していくことで、$K$ の大きい方から答えが求められる。

Python3