CEOI2019 / CodeForces 1192B. Dynamic Diameter


題目簡述:給定一棵$N \leq 10^5$個節點的樹,邊上帶權,維護以下兩個操作:

1. 修改一條邊的邊權;

2. 詢問當前樹的直徑長度。

 

解1:code

注意到樹的直徑有以下性質:

定理:令$\text{farthest}(x)$表示與節點$x$距離最遠的節點的集合。則對任意節點$x$,都有任意$a \in \text{farthest}(x)$與$b \in \text{farthest}(a)$,$a$與$b$的距離即為直徑。

我們任選一個節點$r$作為樹的根,任意邊$(x, y)$,若$x$為$y$的父節點,則把邊權置於節點$y$上,視作點權,記作$w[y]$,則修改邊權都可以視作修改點權。

我們考慮詢問樹的直徑,可以分成兩個步驟:1. 找到離$r$距離最遠的葉子節點$x$。2. 找到離$x$距離最遠的節點$y$。

1. 找到離$r$距離最遠的葉子節點$x$。我們在樹的DFS序$p_1, p_2, \dots, p_n$上查找$\text{dis}(r, p_i)$的最大值及其下標$i$,則$x = p_i$。可在$O(\log n)$時間復雜度內解決。

2. 找到離$x$距離最遠的節點$y$。設$\text{LCA}(x, y) = u$,則$\text{dis}(x, y) = \text{dis}(r, x)+\text{dis}(r, y)-2\text{dis}(r, u)$。考慮樹鏈剖分,在$x$到$r$的路徑中的所有重鏈中,找到最大的節點$u$,使得$\text{dis}(r, \text{light}(u))-2\text{dis}(r, u)$最大,其中$\text{light}(u)$表示節點$u$的輕鏈連接出去的后代節點集合(包括$u$本身)。可在$O(\log^2 n)$時間復雜度內解決。

接下來考慮修改操作,我們只需要維護

1. 步驟1 的 $\text{dis}(r, p_i)$。只需要用線段樹維護區間整體加減,以及區間最值即可。時間復雜度$O(\log n)$。

2. 步驟2 的 $\text{dis}(r, \text{light}(u))-2\text{dis}(r, u)$。同樣需要用線段樹維護區間整體加減,以及區間最值。此外,對於每一個節點$x$,我們都需要一個multiset來維護$\text{light}(x)$中節點$y$的最大值$\text{dis}(r, y)$。時間復雜度為$O(\log^2 n)$。

於是,我們可以在時間復雜度$O(n + q \log^2 n)$內解決。

注:同樣做法,Link-Cut Tree可以在$O(n + q\log n)$的時間內解決。

 

解2:code

如果沒有修改操作,這題可以用動態規划來求解。為方便,與解1一樣,我們以同樣的方式把邊權都放在點上。特別地,$w[r] = 0$。設$f[x][0]$表示以$x$為根的子樹中的直徑長度,$f[x][1]$表示$x$為根的子樹中與節點$x$距離最遠的節點與$x$的距離 加上 節點$x$的權值$w[x]$。於是,我們有

$$ f[x][0] = \max\{ \max_{y \in \text{son}(x)}\{f[y][0]\}, \max_{y_1, y_2 \in \text{son}(x), y_1 \neq y_2}\{f[y_1][1]+f[y_2][1]\} \}, $$

$$ f[x][1] = \max_{y \in \text{son}(x)}\{ f[y][1] \} + w[x]. $$

特別地,若$\text{son}(x) = \emptyset$,則$f[x][0] = 0, f[x][1] = w[x]$;若$\text{son}(x) = \{ y \}$,則$f[x][0] = \max\{f[y][0], f[y][1]\}, f[x][1] = f[y][1]+w[x]$。

 

現在,我們考慮動態DP。將整棵樹樹鏈剖分之后,令

$$ g[x][0] = \max\left\{ \max_{y \in \text{lightson}(x)}\{ f[y][0] \}, \max_{y_1, y_2 \in \text{lightson}(x), y_1 \neq y_2} \{ f[y_1][1]+f[y_2][1] \} \right\}, $$

$$ g[x][1] = \max_{y \in \text{lightson}(x)}\{f[y][1]\}, $$

其中,$\text{lightson}(x) = \text{son}(x) \setminus \{ \text{heavy}(x) \}$,$\text{heavy}(x)$為節點$x$的重兒子。

簡記$y = \text{heavy}(x)$,我們可以得到動態規划方程:

$$ f[x][0] = \max\{ f[y][0], g[x][0], f[y][1]+g[x][1] \}, $$

$$ f[x][1] = \max\{ f[y][1], g[x][1] \} + w[x]. $$

$$ \begin{bmatrix} 0 & g[x][1] & g[x][0] \\ -\infty & w[x] & g[x][1]+w[x] \\ -\infty & -\infty & 0 \end{bmatrix} * \begin{bmatrix} f[y][0] \\ f[y][1] \\ 0 \end{bmatrix} = \begin{bmatrix} f[x][0] \\ f[x][1] \\ 0 \end{bmatrix}, $$

其中$C = A*B$定義為$C_{ij} = \max_k \{ A_{ik}+B_{kj} \}$。

 

於是,我們可用樹鏈剖分在$O(n + q \log^2 n)$的時間復雜度內解決。

注:同樣做法,Link-Cut Tree可以在$O(n + q\log n)$的時間內解決。

再注:事實上矩陣的第一列和最后一行在進行廣義乘法時是不變的,即結果矩陣永遠形如

$$ \begin{bmatrix} 0 & * & * \\ -\infty & * & * \\ -\infty & -\infty & 0 \end{bmatrix}. $$

於是,我們只需要計算上述矩陣中打$*$的部分,見code

 

解3:code

有一個非常巧妙的做法,考慮樹的全DFS序(長度為$2n-1$的DFS序,允許一個節點在這個DFS序中出現多次)$p_1, p_2, p_3, \dots, p_{2n-1}$。

令$\text{index}(x)$表示在全DFS序上節點$x$第一次出現的下標,即$p_{\text{index}(x)} = x$。

考慮兩個節點$x$和$y$,其下標$a = \text{index}(x), b = \text{index}(y)$,不妨設$a \leq b$。這兩個節點之間的距離

$$\begin{aligned} \text{dis}(x, y) & = \text{dis}(r, x)+\text{dis}(r, y)-2\text{dis}(r, \text{LCA}(x, y)) \\ & = \text{dis}(r,x)+\text{dis}(r,y)-2\min_{a \leq c \leq b}\{ \text{dis}(r, p_c) \}. \end{aligned}$$

於是,樹的直徑則為

$$ \max_{x, y}\{\text{dis}(x,y)\}  = \max_{1 \leq a \leq c \leq b \leq 2n-1 } \{ \text{dis}(r, p_a)+\text{dis}(r, p_b)-2\text{dis}(r, p_c) \}.  $$

我們可以用線段樹維護全DFS序在區間上的信息來解決此題,時間復雜度$O(n+q \log n)$。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM