首先考慮二分搜答案,這樣變成對於一個給定的誤差$M$,是否有辦法把邊權都改成$60$的倍數,使得任兩點之間的距離誤差絕對值不會超過$M$。對於一個子樹來說,記他的根為$R$,假設有一種改邊權的方法,使得這棵子樹中任兩點之間的距離誤差絕對值不會超過$M$,並且$R$到這棵子樹中每個點的距離誤差最小值為$a$,最大值為$b$(這裡的誤差指的是「新的距離扣掉舊的距離」的值,有正有負,因此這裡顯然會有$a\leq 0,b\geq 0$),那麼這個設邊權的方法就只有$a,b$是跟之後決策有關的資訊了。也就是一個節點需要的 dp 值會是一大堆的$(a,b)$ 的 pair 。實際上我們可以不用把所有的$(a,b)$都紀錄起來,觀察到如果有兩個 pair $(a_1,b_1),(a_2,b_2)$,滿足$a_2\leq a_1$且$b_2\geq b_1$,那麼取$(a_1,b_1)$一定會比取$a_2,b_2$好,因此我們可以只維護$a$值和$b$值都嚴格遞增的 pair 們就可以了。
轉移比較麻煩,我們可以把題目轉成二元樹比較好DP。轉成二元樹的方法如下圖(對每個節點都做這種轉換即可),其中紅色的點是新加的點,左右圖中的藍色的邊的邊權是相等的,並且紅色邊的邊權為$0$。
轉成二元樹之後工作就只剩下合併兩個子節點的 dp 陣列了,假設當前節點為$x$,並且我們已經決定好$x$連向他兩個子樹的邊的新邊權了,記這兩條邊的誤差分別為$dx,dy$(也就是新邊權扣掉舊邊權的值),那麼考慮左子樹 DP 陣列中的某個$(a_1,b_1)$,還有右子樹中的某個$(a_2,b_2)$,這兩個 pair 分別都代表了他所在子樹的某個設置邊權的方法。接下來我們想知道把這兩個方法並在一起是不是可行的,並且如果可以的話要知道$x$的 DP 陣列必須多丟什麼 pair 進去。我們想要知道這兩個 pair 是否是可行的,而可行的充要條件就是任兩點距離的誤差絕對值$\leq M$。分成$x$到非根節點和左子樹中的點到右子樹中的點來討論,考慮前者則必須滿足:$|a_1+dx|\leq M,|b_1+dx|\leq M,|a_2+dy|\leq M,|b_2+dy|\leq M$。後者的話則必須滿足:$|a_1+a_2+dx+dy|\leq M,|b_1+b_2+dx+dy|\leq M$。並且如果$(a_1,b_1),(a_2,b_2)$都滿足前面那些條件的話,那麼$dp[x]$就會新增一個 pair :$(min(a_1+dx,a_2+dy,0),max(b_1+dx,b_2+dy,0))$。
我們當然不能枚舉所有左右子樹形成的 pair 的二元組,注意到當我們固定$(a_1,b_1)$時,我們可以把上述條件全部整理成:$a_2\leq $一坨東西、$a_2\geq $一坨東西($b_2$)亦同,這裡就可以利用這些 pair 的遞增性,可以得到第二個子樹中滿足那些條件的 pair 會落在某個區間中(如果我們已經把子樹中的 pair 們排好序了),而我們不難用二分搜找出這個區間。再觀察到新增的 pair 的式子,可以不妨設$a_1+dx\leq a_2+dy$,因為我們可以把兩個子樹交換再作一次,因此新增的 pair 的第一項的值已經確定了,並且我們知道此時第二項要越小越好,也就是 $b_2$ 越小越好,因此我們只要枚舉第一個子樹中的$(a_1,b_1)$,並且取剛剛找到的那個區間的第一個 pair 就可以了,拿他配上$(a_1,b_1)$去更新$dp[x]$即可(當然當這個區間不存在時就沒辦法更新)。
