Processing math: 100%

UNIQUE VISION Programming Contest 2024 Summer (AtCoder Beginner Contest 359) G問題メモ

G - Sum of Tree Distance

G - Sum of Tree Distance

いろんな解法がある。

問題

  • N 頂点の木があり、頂点 v には色 Av が塗られている
  • d(u,v) を以下で定義する
    • uv が同じ色で塗られている(Au=Av)とき、uv の距離
    • uv が異なる色で塗られている(AuAv)とき、0
  • N1u=1Nv=u+1d(u,v) を求めよ
  • 2N2×105

解法1 - 平方根で場合分け

同じ色の頂点が何個あるかで色分けする。
閾値 B を決める。

B 個未満の色

同じ色が B 個未満の場合、愚直に全ペアの距離を1つ1つ求める。
オイラーツアー+区間最小値が取得できるSparseTable を前計算しておくことにより、2頂点間の距離は O(1) で求められる。
(言語によってはbit_lengthを求める際に軽い O(logN) がかかるが)

1つの色につき最大 O(B2)、全体では O(B2NB) かかる。
区間最小値をセグ木でやるとlogがつき、若干TLEが厳しくなる。

B 個以上の色

同じ色が B 個以上の頂点は、木DPする。

  • DPa[v]=v 以下の、全ての色 a の頂点の(個数, v までの距離の和)

1つの色につき O(N)、全体では O(NNB) かかる。


この2つのバランスが取れるのは、B=N の時で、全体 O(NN) となる。

PyPyだと数個のテストケースでTLEが取れなかった。
Numbaに書き直すと余裕を持って通った。(約2000ms)

Python3

解法2 - 木DP+マージテク

距離計算の部分にちょっとした工夫が必要になるが、こちらの方が実装量は少ない。
ただ、ライングラフ+色の種類が多いテストケースに対して O(N2) の空間計算量が必要になるのでMLEの危険性がある? (まぁ、定数倍が大きいわけではないし、MLEの制限はTLEと比べると緩いので大丈夫か)

1回の木DPで、全ての色について求める。

  • DP[v,a]= 頂点 v 以下の部分木で、色 a の全ての頂点の(個数, 深さの総和)

例えば解法1のDPでは「頂点 v までの距離の総和」を値として持ったため、頂点を遡る毎に更新が必要になった。
しかし、マージテクをする場合は、小さい方を大きい方にマージする分、大きい方は更新が発生してはいけない。

「深さ」を値として持つことで、距離を求めることを可能にしつつ、更新が発生しないようにできる。
「子孫 u から祖先 v までの距離」=「u の深さ - v の深さ」

これで、a の種類数が少ない方を多い方にマージしていくことで、時間計算量は O(NlogN) となる。
DPの値は、配列で持つと明確に O(N2) の空間を要するため、基本的には辞書で持つことになる。これに log がかかる言語では、O(Nlog2N) となる。

Python

その他の解法

  • 重心分解
  • Auxiliary Tree
programming_algorithm/contest_history/atcoder/2024/0622_abc359.txt · 最終更新: 2024/06/25 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0