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