樹鏈剖分學習

2022-05-29 08:48:08 字數 3398 閱讀 2657

兩次dfs,第一次處理處fa,depth,size,son,第二次處理出top,rank,id

一條重鏈的編號是連續的,可以用資料結構維護,做事情的時候判斷是否在同一條鏈上,不是就把最深的跳到鏈頭的fa,然後繼續判斷

luogu3384 【模板】樹鏈剖分

區間加,求和,子樹加,求和

#include#include

#include

#include

#include

#include

#define ll long long

using

namespace

std;

const

int maxn=200005

;inline

intread()

while(ch>='

0'&&ch<='9')

return k*x;

}int

rt,cnt,ecnt,fir[maxn],nex[maxn],to[maxn];

intf[maxn],d[maxn],size[maxn],son[maxn],rk[maxn],top[maxn],id[maxn],val[maxn];

struct

nodea[maxn*2

];int

n,m,r,opt,x,y;

ll p,k;

void build(int u,int l,intr)}

void addd(int

u,ll v)

void pushdown(intu)}

void update(int u,int l,int

r,ll v)

}ll query(

int u,int l,int

r)void addedge(int u,int

v)void dfs1(int u,int fa,int

depth)

}void dfs2(int u,intt)}

int sum(int x,int

y)

else

fx=top[x];

fy=top[y];

}if(id[x]<=id[y]) ans+=query(1,id[x],id[y]),ans%=p;

else ans+=query(1,id[y],id[x]),ans%=p;

}void updates(int x,int y,int

c)

else

fx=top[x];

fy=top[y];

}if(id[x]<=id[y]) update(1

,id[x],id[y],c);

else update(1

,id[y],id[x],c);

}int

main()

for(int i=1;i)

cnt=0

; dfs1(r,

0,1);

dfs2(r,r);

cnt=1

; build(

1,1,n);

for(int i=1;i<=m;i++)

else

if(opt==2

)

else

if(opt==3

)

else

}return0;

}

view code

[jloi2014]松鼠的新家

相當於n-1次+1,每次把a[i]~a[i+1]的區間+1,由於a[2]~a[n]會加兩次,所以這些還要-1

//

luogu-judger-enable-o2

#include#include

#include

#include

#include

#include

#define ll long long

using

namespace

std;

const

int maxn=300005

;const

int maxm=600005

;inline

intread()

while(ch>='

0'&&ch<='9')

return k*x;

}int

rt,cnt,ecnt,fir[maxn],nex[maxm],to[maxm];

intf[maxn],d[maxn],size[maxn],son[maxn],rk[maxn],top[maxn],id[maxn],val[maxn];

struct

nodea[maxm*2

];int

n,m,r,opt,x,y;

ll p,k;

void build(int u,int l,intr)}

void addd(int

u,ll v)

void pushdown(intu)}

void update(int u,int l,int

r,ll v)

}ll query(

int u,int l,int

r)void addedge(int u,int

v)void dfs1(int u,int fa,int

depth)

}void dfs2(int u,intt)}

int sum(int x,int

y)

else

fx=top[x];

fy=top[y];

}if(id[x]<=id[y]) ans+=query(1

,id[x],id[y]);

else ans+=query(1

,id[y],id[x]);

}void updates(int x,int y,int

c)

else

fx=top[x];

fy=top[y];

}if(id[x]<=id[y]) update(1

,id[x],id[y],c);

else update(1

,id[y],id[x],c);

}int

main()

dfs1(

1,0,1

); dfs2(

1,1);

build(

1,1,n);

for(int i=1;i)

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

return0;

}

view code

樹鏈剖分學習

樹鏈剖分 看了學習了樹鏈剖分 適用於在樹上的路徑操作。關鍵在於重鏈的構造,把它表示到了資料結構上的連續區間,降低了複雜度。主要操作步驟實際上有三個部分 1 構造重鏈 2 如何維護資料 3 分解為輕重鏈的查詢與修改 include include include include define n 10...

樹鏈剖分學習

之前寫過樹剖的題,但沒有完全理解,現在又無法複述思路了,所以重新學習一下,部分語句參考大神的敘述 一 概念 樹鏈剖分,顧名思義,樹是由一根根樹鏈組成的,我們現在要來把它按鏈來分解掉。我們知道,大部分樹上的問題都是圍繞樹的路徑來做文章,分解成一條條的鏈之後,我們就可以對節點 邊 就行編號了,而同一根鏈...

樹鏈剖分學習

樹鏈剖分其實就是把一棵樹剖分成一條條鏈 重鏈輕鏈 然後用線段樹進行操作維護。複雜度logn 記錄 deep size fa pos bl 陣列 deep深度,size子樹節點個數,pos節點編號,bl所在重鏈頂端節點編號,fa父親編號。例題 bzoj1036 include define inf 1...