目次

freee Programming Contest 2023(AtCoder Beginner Contest 310)G問題メモ

freee Programming Contest 2023(AtCoder Beginner Contest 310)

男子達が水泳をやる会社ではなく、会計管理サービスを中心に提供する会社。

G - Takahashi And Pass-The-Ball Game

G - Takahashi And Pass-The-Ball Game

問題

解法

求めるのは期待値だが、$K$ で割る前の値である「$1,2,...,K$ 回操作後に渡されるボールの個数の合計」が各人についてわかればよい。

つまり、各頂点 $i$ から $1,...,K$ 回後に訪れる頂点のそれぞれに $B_i$ を加算したい。
もちろんこれを愚直に行うことは時間制約上できない。

$i→A_i$ に辺を張ったグラフはFunctional Graphなので、各連結成分はループが1つとそこに流入する木からなることを利用する。

「ループ上」「木の根に向かうパス上」それぞれにおける区間加算は、累積和を用いて高速化できる。

加算したい頂点がループ上か木上かを区別して、別々に扱うことで実現できる。

ループ上の累積和

ループ上の累積和は、適当な点で切り開いて、「どこから累積和を始めるか」を固定することが重要となる。

その上で、「①最初の周回の末尾まで」「②周回分」「③残り」の3つに分けて加算するとやりやすい。

○→○→●→○→○
        Bi
            + ---- -           ①
+ ---------------- -  x周回分  ②
+ ---- -                       ③

木上の累積和

ループ上の各頂点を根とした木をDFSで辿る。

ループ     r
→○→○→◎→○→○→
          ↑
          ◎
         ↗↖        i
        ○  ◎←◎←●

根 $r$ までのパスを持ちながらDFSする。木上の累積和で加算するのは

このようにし、葉から根に向かって累積和を取っていく($Ans[A_i]+=Ans[i]$)と、 パスへの区間加算を表現できる。

Python3