學這個之前應該要比較熟悉重鏈剖分,推薦一下這篇部落格。
我們模擬重鏈剖分,定義每個點所有兒子中,子樹深度最大的點為它的重兒子,那麼整棵樹就被劃分成了一些不相交的重鏈,然後首先就有乙個性質那就是所有重鏈長度和是\(o(n)\)級別的,這個東西很顯然,還有乙個性質就是乙個點的k級祖先所在重鏈長度一定大於等於k,這個東西考慮反證法,假設小於k,那麼當前點顯然會和這個點在一條重鏈上,然後就沒了。
1.例題 lxhgww的奇思妙想,這個是模板題就不講解了。
這個思想有點像啟發式合併,大概是直接繼承重兒子的dp值,然後輕兒子暴力合併,因為總鏈長是\(o(n)\)的,所以轉移的複雜度就是\(o(n)\)的,一般來說我們可以利用陣列指標來完成這個操作,把重兒子的陣列指標設為當前點的$\pm$1,給剩下的輕兒子分配剩餘的記憶體就好了。
1.例題 [poi2014]hotel加強版,題意是統計有多少種方案可以從樹上選出3個點使得它們兩兩間距離相等。
我們首先來考慮如何統計點,有兩種情況,一種是都在乙個點的子樹內,第二種是兩個點在子樹內,另乙個點在子樹外,我們分開來討論這兩種情況,設\(f[x][j]\)表示x子樹內距離\(x\)為\(j\)的點數,\(g[x][j]\)為\(x\)子樹內有多少對點\((u,v)\)滿足\(dis(u,x)=dis(v,x)=d\),且\(dis(u,v)=d+j\),那麼我們有以下轉移:
\[f[u][j]=\sum_vf[v][j-1]\\g[u][j]=\sum_vg[v][j+1]+f[u][j]\times f[v][j-1]\\ans=\sum_\sum_u\sum_vf[u][k]\times g[v][k+1]+g[u][k]\times f[v][k-1]$$
注意轉移順序,複雜度$o(n^2)$。
我們發現這個dp是以深度為下標的,那麼我們對這棵樹進行長鏈剖分,對於重兒子我們直接用指標偏移,讓$f[x]=f[son[x]]-1,g[x]=g[son[x]]+1$,由於我們是先訪問父親的,所以移下項就好了,然後注意因為$f$是不斷往後面偏移的,$g$是不斷往前面偏移的,所以每次給乙個點分配空間就要開兩倍重鏈長,$f$和$g$分別定位在兩端,這樣讓$f$不斷往前偏移,$g$不斷往後偏移,這樣子就不會有空間被共用了,複雜度$o(n)$,[**戳我](
2.例題 [[wc2010]重建計畫](題意是給你一顆帶邊權的樹,要求你找一條路徑滿足路徑長度在$[l,r]$之間,並且最大化路徑權值和與路徑長度之比。
對於分數規劃我們套路是二分答案,把分母乘過去那麼乙個答案可行條件為:$$\sum val-mid\times len\ge0\]
那麼我們把每條邊邊權都減去\(mid\),那麼只需要存在一條長度和大於等於\(0\)的路徑即可,我們利用:$$dis(x,y)=dep(x)+dep(y)-dep(lca(x,y))*2$$
在這裡\(dep(x)\)是從根節點到x點的路徑權值和。
其實用的比較多的還是優化dp,這類dp特徵也很明顯就是以深度為下標,做題的時候注意一下就好了,如果不是以深度為下標的話用啟發式合併也可以做到很優秀的乙個\(\log\)的複雜度,其實最重要的還是推和樹上距離有關的轉移方程,只要方程能寫出來優化也都是比較套路的東西了。
學習筆記 長鏈剖分
處理和深度有關的一些事情 長鏈剖分的 和重鏈剖分一樣。只是重兒子條件不同罷了。之前和沒學一樣。補充 本質是優化dp,dp一維和深度有關 實現有一些類似dsu on tree 長鏈剖分還有乙個操作精髓是繼承長兒子的資訊 通常用指標分配記憶體,使得長兒子資訊更新位置恰好是x的位置偏移一位 共用部分陣列,...
長鏈剖分學習筆記
長鏈剖分,也屬於樹鏈剖分的一種方式,但是其與經典的重鏈剖分又不太一樣。在重鏈剖分中,我們評判兒子重或輕的方式是比較其子樹節點數量。在長鏈剖分中,我們以子樹中最深的葉節點深度的大小來比較。其他步驟與重鏈剖分類似,都是兩遍dfs即可解決,都是o n 的複雜度。接下來,我們來看兩個長鏈剖分的經典問題.時間...
長鏈剖分學習筆記
終於認真寫一次標題了 因為一些不明原因,之前對 dsu on tree 的理解沒有完全寫出來,在這裡會一起寫,因為兩者極為相似。先來看一下 dsu on tree 和長鏈剖分的對比。dsu on tree 實際上就是重鏈剖分,可以處理很多與子樹有關且不帶修改的題目 離線 複雜度 mathcal nl...