學了這么久的點分治 / 點分樹,感覺自己還是只會做點裸題……這都要國賽了感覺自己吃棗葯丸。
CSAcademy Round 10 Yury's Tree
題意
給定一棵 \(n\) 個點的樹,每條邊有一個邊權。接下來有 \(m\) 次操作分為以下兩種:
1 u
查詢 \(u\) 號點的價值。2 x y z
表示對於 \(x\) 子樹的所有點 \(u\) ,如果 \(u\) 到 \(x\) 的路徑上的邊權全都大於等於 \(y\) ,就給 \(u\) 的價值加上 \(z\) 。\(n,m \le 3 \times 10^5 , TL = 1.5s\) 。原題范圍 \(n,m \le 10^5,TL = 4s\)
題解
原題的做法是個不太優美的根號算法,事實上這個題是存在 \(\log\) 級別做法的。
首先假設修改全部在詢問之前。注意到這里你需要保證路徑最大值大於等於某個數,因此可以考慮一下點分治。分治到當前分治重心的時候,把分治重心沿原樹的父親往上爬,直到遇到上一分治重心或根節點,把這條路徑上的有效修改操作提取出來。某一次查詢的點 \(u\) 如果可以被修改操作 \((x,y,z)\) 貢獻到,那么 \(u\) 到分治重心的最大邊權 \(w\) 就要小於等於 \(y\)。這可以很容易地統計出來。
我們再加上時間這一維,就只要拿一個樹狀數組維護就行了,復雜度 \(O(n \log^2 n)\) 。
總結
對於有根樹上的一些問題,思路也不要被局限,點分治也是一個很好的角度;對於樹上的某些單點查詢,可以考慮修改對查詢的貢獻,而不是把整個值維護出來。
一個經典問題
題意
給出一棵 \(n\) 個點的有根樹,每個結點上有一個一次多項式。求每個結點到根的多項式乘積的和。
\(n \le 10^5\) 。
題解
樹上路徑問題,可以繼續考慮點分治。點分治之后,假如求出了當前分治重心到根節點的多項式乘積,那么接下來只需要對於每一個不包含根節點的子樹,計算以這個子樹的根節點為新的根,關於這個子樹的一個子問題即可。最后加起來統一卷積。
考慮如何求出這條路徑的多項式乘積,直接暴力分治 \(\text{FFT}\) 是 \(O(n \log^2 n)\) 的,加上點分治就是 \(O(n \log^3 n)\) ,不太能過。注意到其實這個分治 \(\text{FFT}\) 有大量的重復計算,因此優化可以從這里下手。我們只需要不斷地找到該路徑上的下一個點分中心,就可以直接得到下一個點分中心到根的路徑的乘積,這樣可以得到 \(O(\log n)\) 個多項式,其中第 \(i\) 個多項式長度級別不會超過 \(\frac{n}{2^i}\)。顯然把他們卷起來的時間復雜度是 \(O(n \log n)\),因此總復雜度降到了 \(O(n \log^2 n)\) 。
Codeforces 936E Iqea
題意
有一間房子由 \(n\) 個格子組成,第 \(i\) 個格子位於坐標 \((x_i,y_i)\) ,保證所有屬於房子的格子是四連通的,同時保證所有不屬於房子的格子也是四連通的。
房子里有好多的橘貓。橘貓想吃東西。接下來會發生 \(m\) 個事件,第 \(i\) 個事件可以用三個數 \(ty,x,y\) 表示。
若 \(ty = 1\) 則表示坐標 \((x,y)\) 處出現了一大碗貓糧,貓糧是吃不完的。
若 \(ty = 2\) 則表示坐標 \((x,y)\) 處出現了一只橘貓,他會走向距離最近的貓糧去吃,注意貓不能走出房子。保證坐標都在房子內。
對於每個 \(ty = 2\) 的事件,橘貓想讓你告訴他們,距離最近的貓糧距離是多少。
\(n,m,x_i,y_i \le 3 \times 10^5\) 。
題解
由於屬於房子和不屬於房子的格子都是四聯通的,因此聯通部分不存在環。
如果把所有垂直方向上相鄰的格子縮成一個點,那么這樣就形成了一棵樹。考慮一只橘貓和一碗貓糧在枚舉了相遇的那個節點之后,應該怎么算距離。可以發現,一定是先找到對應的到這個節點的最短路徑,然后在這個節點上走完剩下的路。這樣的話,只要在每個分治重心存下這個分治區域中,所有的貓糧到該分治重心的最短距離,以及到了之后的位置,詢問時就可以到每個分治中心去查詢了。由於到每個分治重心處還需要 \(O(\log n)\) 的代價維護,因此時間復雜度 \(O(n \log^2 n)\) 。
總結
模型轉化是這道題的一大核心;對於樹上動態維護一個點到一個點集的最短路,可以考慮用點分樹來維護;可以把分治重心當做類似中轉站的處理點。
Luogu P5311
題意
給定一棵 \(n\) 個點的樹,每個節點有一個顏色。\(q\) 詢問從 \(x\) 出發,只經過編號在 \([l,r]\) 中的點,所能到達的點的顏色種數。
\(n,q \le 10^5\) 。
題解
建出點分樹,一個很重要的性質是,對於詢問 \((l,r,x)\) 中 \(x\) 所在的一個連通塊,必定完全包含在點分樹上某一個節點 \(p\) 的子樹里,滿足 \(p \in [l,r]\)。證明可以考慮,如果不存在這樣的 \(p\) ,那么這個聯通塊必然會被某個分治重心分開成若干個聯通塊。
接下來我們只要沿着點分樹向上爬,就不難找到這個 \(p\) 。對於當前分治重心,求出每個點到這個分治重心的路徑編號最大最小值,問題就可以化為,給定若干個區間,每個區間有一種顏色,每次詢問會給定一個區間 \([l,r]\) ,求被 \([l,r]\) 完整包含的區間顏色種數。不難發現只需要離線樹狀數組掃一遍就行了,復雜度 \(O(n \log^ 2 n)\) 。
總結
題目的難點主要在前面的性質發現。思路可能要有意識地往這上面靠。