−目次
UNIQUE VISION Programming Contest 2024 Summer (AtCoder Beginner Contest 359) G問題メモ
G - Sum of Tree Distance
いろんな解法がある。
問題
- NN 頂点の木があり、頂点 vv には色 AvAv が塗られている
- d(u,v)d(u,v) を以下で定義する
- uu と vv が同じ色で塗られている(Au=AvAu=Av)とき、uu と vv の距離
- uu と vv が異なる色で塗られている(Au≠AvAu≠Av)とき、00
- N−1∑u=1N∑v=u+1d(u,v)N−1∑u=1N∑v=u+1d(u,v) を求めよ
- 2≤N≤2×1052≤N≤2×105
解法1 - 平方根で場合分け
同じ色の頂点が何個あるかで色分けする。
閾値 BB を決める。
BB 個未満の色
同じ色が BB 個未満の場合、愚直に全ペアの距離を1つ1つ求める。
オイラーツアー+区間最小値が取得できるSparseTable を前計算しておくことにより、2頂点間の距離は O(1)O(1) で求められる。
(言語によってはbit_lengthを求める際に軽い O(logN)O(logN) がかかるが)
1つの色につき最大 O(B2)O(B2)、全体では O(B2NB)O(B2NB) かかる。
区間最小値をセグ木でやるとlogがつき、若干TLEが厳しくなる。
BB 個以上の色
同じ色が BB 個以上の頂点は、木DPする。
- DPa[v]=vDPa[v]=v 以下の、全ての色 aa の頂点の(個数, vv までの距離の和)
1つの色につき O(N)O(N)、全体では O(NNB)O(NNB) かかる。
この2つのバランスが取れるのは、B=√NB=√N の時で、全体 O(N√N)O(N√N) となる。
PyPyだと数個のテストケースでTLEが取れなかった。
Numbaに書き直すと余裕を持って通った。(約2000ms)
解法2 - 木DP+マージテク
距離計算の部分にちょっとした工夫が必要になるが、こちらの方が実装量は少ない。
ただ、ライングラフ+色の種類が多いテストケースに対して O(N2)O(N2) の空間計算量が必要になるのでMLEの危険性がある?
(まぁ、定数倍が大きいわけではないし、MLEの制限はTLEと比べると緩いので大丈夫か)
1回の木DPで、全ての色について求める。
- DP[v,a]=DP[v,a]= 頂点 vv 以下の部分木で、色 aa の全ての頂点の(個数, 深さの総和)
例えば解法1のDPでは「頂点 vv までの距離の総和」を値として持ったため、頂点を遡る毎に更新が必要になった。
しかし、マージテクをする場合は、小さい方を大きい方にマージする分、大きい方は更新が発生してはいけない。
「深さ」を値として持つことで、距離を求めることを可能にしつつ、更新が発生しないようにできる。
「子孫 uu から祖先 vv までの距離」=「uu の深さ - vv の深さ」
これで、aa の種類数が少ない方を多い方にマージしていくことで、時間計算量は O(NlogN)O(NlogN) となる。
DPの値は、配列で持つと明確に O(N2)O(N2) の空間を要するため、基本的には辞書で持つことになる。これに log がかかる言語では、O(Nlog2N)O(Nlog2N) となる。
その他の解法
- 重心分解
- Auxiliary Tree

