(点)分治学习笔记
嘩我看了一下好像沒有很詳細專門講分治的blog?那就主要先學一下點分治吧,其他的……等我記得把C++一本通帶到機房來再說吧先咕著啦
寫在前面
刷題進度
入門題(0/3)
好題(0/9)
問題解決進度
Q1
Q2
?正文
淀粉質
點分治
點分治就是在一棵樹上,對具有某些限定條件的途徑靜態地進行統計的算法。
——《算法競賽 進階指南》(李煜東)
這句話看起來很高深的樣子……(這本書上的話都很高深)
讓我們來結合題目理解一下↓
【例】Tree? (POJ1741)
題目大意
給定一棵有n個結點的樹,每條邊都有一個權值。樹上兩個結點x與y之間的路徑長度就是路徑上各條邊的權值之和。求長度不超過k的路徑有多少條。
解題思路
本題樹中的邊是無向的,即這棵樹是一個由n個結點,n-1條邊構成的無向連通圖,即這是一棵無根樹。
若指定結點p為根,則對于p來說,樹上的路徑可以分為兩類:
1.經過根結點p
2.包含于p的某一棵子樹中(不經過根結點)
根據分治的思想,對于第2類路徑,顯然可以把p的每棵子樹作為子問題,遞歸處理
然而……對于第1類路徑,可以從根結點p分成"x~p"與“p~y”兩段(——話說這不是和LCA有點聯系??),于是從p出發對整棵樹DFS,求出d[i]表示i結點到根結點p的距離,b[i]表示i屬于根結點p的哪一棵子樹(注意b[p]=p)
此時滿足題目要求的第1類路徑就是滿足以下兩個條件的點對(x,y)的個數
——這句話特別奇怪(我感jio)……我的理解就是
如果點對(x,y)滿足以下兩個條件,那么x到y的路徑就是上面提到的第1類路徑且路徑長度滿足題目不超過k的要求
條件如下:
1.b[x]≠b[y]
2.d[x]+d[y]≤k
那么接下來問題來了——如何統計上述點對的個數呢?
定義函數Calc(p)表示在以p為根的樹中統計上述點對(x,y)的個數
有兩種實現方法:
1.樹上直接統計
2.指針掃描數組
接下來分別介紹一下這兩種方法QWQ
一、樹上直接統計
設p的子樹為s1,s2,s3……sm
對于si中的每個結點x,把在子樹s1,s2,s3……si-1中的滿足d[x]+d[y]≤k的結點y的個數直接累加到答案中即可
具體來說,可以建立一個樹狀數組,依次處理每棵子樹si
對si中的每個結點x,操作如下:
1.查詢前綴和ask(k-d[x]),即為所求的y結點的個數
2.執行add(d[x],1),表示與p距離為d[x]的結點增加了一個
我感jio不太明白這里要怎么實現啊……書上又沒有代碼,我還是去問一下dalao吧QAQ
go back
繼續……
按子樹一棵棵處理保證了b[x]≠b[y],查詢前綴和保證了d[x]+d[y]≤k
注意
樹狀數組的范圍與路徑長度有關,這個范圍遠比n要大,本題不易進行離散化
一種解決方案是用平衡樹代替樹狀數組,以保證O(nlogn)的復雜度,但這樣代碼復雜度會顯著增加
(真的是“顯著”增加呀,因為我根本就不會平衡樹QAQ,離散化也不太清楚天哪我簡直是個渣渣QAQ)
兩種方法各有千秋,對于這道例題來說,第二種方法更加合適,所以我接下來要講一講第二種方法
二、指針掃描數組
先把樹中的每一個結點放進一個數組a,并按照結點距離根結點的距離(即d的值)排序
使用兩個指針L,R分別從前、后開始掃描a數組
容易發現一個規律:
在指針L從左向右掃描的過程中,恰好使得d[a[L]]+d[a[R]]≤k的指針R的范圍是從右向左單調遞減的
另外,用數組cnt[s]維護在L+1與R之間滿足b[a[i]]=s的位置i的個數
于是,當路徑的一段x=a[L]時,滿足題目要求的路徑另一端y的個數就是R-L-cnt[b[a[L]]]
然后就……結束了?QAQ我也不懂怎么實現啊救命啊啊啊啊啊
go back
整理一下整個點分治算法的過程
1.任選一個根結點p(下面有說選根結點時的具體要求)
2.從p出發執行一次DFS,求出d數組和b數組
3.執行Calc(p)函數
4.刪除根結點p,對p的每棵子樹(同樣看做是無根樹)遞歸執行1~4步直至葉子結點(結束)
時間復雜度
在點分治過程中,每一層的所有遞歸過程合計對每個結點處理1次
因此,若遞歸到第T層,則整個算法的時間復雜度就是O(Tnlogn)
如果問題中的樹是一條鏈,最壞情況下每次都以鏈的一端為根,那么點分治將需要遞歸n層,時間復雜度退化到O(n2logn)
為了避免這種情況,我們每次選擇樹的重心作為根結點p
此時易證p的每棵子樹大小不會超過整棵數大小的一半,點分治至多就遞歸logn層,所以整個算法的時間復雜度為O(nlong2n)
常見問題
點分治主要可以解決的問題就是處理路徑統計還有處理換根統計問題
要刷的題目
入門題? (go back)
LuoguP3806
LouguP4178
CF116D
好題(我覺得我一輩子都做不完這些題的)
樹上的點對
開店
捉迷藏
qtree5
重建計劃
Race
快遞員
樹的難題
樹上游戲
?
關于重心
樹的重心是什么?(有種小學作文開頭的趕腳)
如果把一個結點x從樹中刪除,那么原來的樹就分成了若干個連通塊,而max表示這些連通塊中最大的那個連通塊的大小
若用max[x]記錄刪除結點x后產生的最大連通塊的大小
那么整個max數組中若max[p]最小,則稱結點p為這棵樹的重心
go back
轉載于:https://www.cnblogs.com/THWZF/p/10359578.html
總結
- 上一篇: 剑网3多少钱啊?
- 下一篇: 【Linux基础】文件处理实例