學習筆記 長鏈剖分

2022-02-05 10:57:06 字數 3413 閱讀 7023

處理和深度有關的一些事情

長鏈剖分的**和重鏈剖分一樣。只是重兒子條件不同罷了。

之前和沒學一樣。。。

補充:本質是優化dp,dp一維和深度有關

實現有一些類似dsu on tree

長鏈剖分還有乙個操作精髓是繼承長兒子的資訊

通常用指標分配記憶體,使得長兒子資訊更新位置恰好是x的位置偏移一位

共用部分陣列,相對獨立又相互依存,這點和dsu on tree有不同

用到的長鏈剖分性質:最長

使得:1.利於分配記憶體

2.當前x的最大深度從長兒子繼承過來,所以陣列一定是最深的。減少討論

3.k級祖先所在鏈長大於等於k

利用k級祖先的鏈一定長度大於等於k的條件。配合預處理倍增陣列、鏈頂記錄資訊、二進位制拆分出最高位。實現o(1)查詢

因為長鏈之和是n,所以對每個長鏈處理的複雜度都是正確的。

模板題。最大值位置在更新時候進行偏移即可。

**:

#include#define reg register int

#define il inline

#define fi first

#define se second

#define mk(a,b) make_pair(a,b)

#define numb (ch^'0')

using

namespace

std;

typedef

long

long

ll;template

il void rd(t &x)

template

il void output(t x)

template

il void ot(t x)

template

il void prt(t a,int st,int nd)

namespace

miraclee[

2*n];

inthd[n],cnt;

int *f[n],memchi[n],ans[n],*cur=memchi;

void add(int x,int

y)void dfs(int x,int

fa) len[x]=len[son[x]]+1;}

void dp(int x,int

fa) }

if(f[x][0]==f[x][ans[x]]) ans[x]=0;}

intmain()

dfs(

1,0);

f[1]=cur;cur+=len[1

]; dp(

1,0);

for(reg i=1;i<=n;++i)

return0;

}}signed main()

/*author: *miracle*

date: 2019/3/17 15:44:31

*/

view code

0/1分數規劃,二分答案,記錄深度為j的點權和最小值,m是固定的,直接更新答案

平移陣列,整體加上ci,用tag[x]維護整體加

主要還是dp式子吧,,,

bzoj3522: [poi2014]hotel

n<=1e6個點,邊權為1,求樹上不超過l的鏈的條數

f[x][j],長度小於等於j的點的個數

可以利於我們列舉y的一邊,直接貢獻答案。

合併有點苟,因為是乙個字首和,所以不斷更新tag[x],len[x]>len[y]的超過的部分,都加上f[y][len[y]-1]。

**:

//

luogu-judger-enable-o2

#include#define reg register int

#define il inline

#define fi first

#define se second

#define mk(a,b) make_pair(a,b)

#define numb (ch^'0')

using

namespace

std;

typedef

long

long

ll;template

il void rd(t &x)

template

il void output(t x)

template

il void ot(t x)

template

il void prt(t a,int st,int nd)

namespace

miraclee[

2*n];

inthd[n],cnt;

void add(int x,int

y)int *f[n],memchi[n],*cur=memchi;

intlen[n],son[n];

inttag[n];

void dfs(int x,int

fa) len[x]=len[son[x]]+1;}

ll ans;

void dp(int x,int

fa) ll tmp=f[y][len[y]-1]+tag[y];

for(reg j=1;j<=len[y];++j)

f[x][

0]-=tmp;

tag[x]+=tmp;

}//cout<

for(reg i=0;i//

cout/

}cout/

cout<

intmain()

dfs(

1,0);

//prt(len,1,n);

//prt(son,1,n);

f[1]=cur;cur+=len[1

]; dp(

1,0);

printf(

"%lld

",ans);

return0;

}}signed main()

/*author: *miracle*

date: 2019/3/17 18:10:50

*/

view code

長鏈剖分思想是基於和深度有關的dp

dsu on tree思想是莫隊,全域性資料結構維護,暴力新增子樹刪除子樹

dsu on tree由於可以全域性維護並且子樹暴力查詢,可以做的事情是長鏈剖分的超集

但是長鏈剖分在特殊情況下的o(n)是無法超越的

長鏈剖分學習筆記

學這個之前應該要比較熟悉重鏈剖分,推薦一下這篇部落格。我們模擬重鏈剖分,定義每個點所有兒子中,子樹深度最大的點為它的重兒子,那麼整棵樹就被劃分成了一些不相交的重鏈,然後首先就有乙個性質那就是所有重鏈長度和是 o n 級別的,這個東西很顯然,還有乙個性質就是乙個點的k級祖先所在重鏈長度一定大於等於k,...

長鏈剖分學習筆記

長鏈剖分,也屬於樹鏈剖分的一種方式,但是其與經典的重鏈剖分又不太一樣。在重鏈剖分中,我們評判兒子重或輕的方式是比較其子樹節點數量。在長鏈剖分中,我們以子樹中最深的葉節點深度的大小來比較。其他步驟與重鏈剖分類似,都是兩遍dfs即可解決,都是o n 的複雜度。接下來,我們來看兩個長鏈剖分的經典問題.時間...

長鏈剖分學習筆記

終於認真寫一次標題了 因為一些不明原因,之前對 dsu on tree 的理解沒有完全寫出來,在這裡會一起寫,因為兩者極為相似。先來看一下 dsu on tree 和長鏈剖分的對比。dsu on tree 實際上就是重鏈剖分,可以處理很多與子樹有關且不帶修改的題目 離線 複雜度 mathcal nl...