樹鏈剖分模板

2022-07-25 08:12:07 字數 3803 閱讀 4573

摘自部落格:

博主講得十分的清楚

以下是帶有注釋的**:

1/*2

這是乙份自用的樹鏈剖分模板,

3自己加的注釋,便於更好的理解

4該模板支援的操作:

51.換根

62.一條鏈上點權加

73.乙個子樹內點權加

84.詢問一條鏈上點權的和

95.詢問乙個子樹內的點權和

106.求lca

11*/

12 #include13

#define numm ch-48

14#define pd putchar(' ')

15#define pn putchar('\n')

16#define pb push_back

17#define debug(args...) cout

#define bug cout<

19using

namespace

std;

20 template 21

void read(t &res)

27 template 28

void

write(t x)

33 typedef long

long

ll;34

const

int inf=0x3f3f3f3f;35

const

int maxn=1e5+10;36

/*建圖部分

*/37

struct node

40 node(int v,int

net):v(v),net(net){}

41 }e[maxn<<1];///

樹有雙向邊,邊數*2

42int

head[maxn],cnt,n;

43void

init()

48void addedge(int u,int v)

54int id[maxn],rk[maxn],fa[maxn],top[maxn],dep[maxn],son[maxn],sze[maxn],val[maxn],root=1;55

//id[u]:點u的dfs序,一條重鏈上的點標號連續

56//

sze[u]:點u的子樹結點個數,包含點u

57//

son[u]:點u的重兒子的id

58//

fa[u]:點u的父親,根結點1的父親為0

59//

top[u]:點u所在重鏈的頭結點,輕鏈則為本身,則top[u]=u;

60//

val[u]:點u的初始權值

61//

rk[id[u]]:id[u]對應的u結點

62//

dep[u]:dfs時,u對應的深度

63int minp[maxn<<2

];64 ll sum[maxn<<2],lazy[maxn<<2

];65

/*線段樹部分

*/66

//sum[k]:點k所在區間的樹結點總和

67//

lazy[k]:點k所在區間的樹結點總和的懶標記

68//

minp[k]:點k所在區間內的最小深度的點u的下標

69int get_minp(int a,int b)

75void pushup(int

k) 79

void pushdown(int k,int l,int r,int

mid)

87void build(int k,int l,int r)

93int mid=l+r>>1

;94 build(k<<1

,l,mid);

95 build(k<<1|1,mid+1

,r);

96pushup(k);97}

98void update(int k,int l,int r,int ql,int qr,ll w)

104int mid=l+r>>1

;105 pushdown(k,l,r,mid);///

attention!!!

106if(ql<=mid) update(k<<1

,l,mid,ql,qr,w);

107if(mid1|1,mid+1

,r,ql,qr,w);

108pushup(k);

109}

110int query_pos(int k,int l,int r,int ql,int qr)

118 ll query_sum(int k,int l,int r,int ql,int qr)

126/*

樹剖部分

*/127

void dfs1(int u)

139}

140void dfs2(int u,int

root)

152}

153int lca(int a,int b)

158if(dep[a]>dep[b]) swap(a,b);

159return

a;160

}161

int upto(int a,int b)

170if(dep[a]>dep[b]) swap(a,b);

171172 ans=get_minp(ans,query_pos(1,1,n,id[a]+1,id[b]));///

不能包含u點,所以+1

173return

ans;

174}

175int check(int u)

182void add_chain(int a,int b,ll w)

188if(dep[a]>dep[b]) swap(a,b);

189 update(1,1

,n,id[a],id[b],w);

190}

191 ll ask_chain(int a,int b)

198if(dep[a]>dep[b]) swap(a,b);

199 ans+=query_sum(1,1

,n,id[a],id[b]);

200return

ans;

201}

202void add_tree(int u,ll w)

209else update(1,1,n,id[u],id[u]+sze[u]-1

,w);

210}

211 ll ask_tree(int u)

218else

return query_sum(1,1,n,id[u],id[u]+sze[u]-1

);219

}220

intmain()

221232

dfs1(root);

233 cnt=0; ///

attention!!!

234 dfs2(1,1

);235 build(1,1

,n);

236int

m;237

read(m);

238while(m--)

245else

if(oper==2)

249else

if(oper==3)

253else

if(oper==4)

257else

if(oper==5)

261}

262return0;

263 }

view code

樹鏈剖分 模板

class match node a n struct no no aa n 4 void init void addpage int x,int y void dfs int s,int faa,int h 根節點,父節點和深度的 if max 0 son s sign void dfs2 int...

模板 樹鏈剖分

define maxn 50010 define l u u 1 define r u u 1 1 寫在類裡面爆棧 int n,m,q int tim 時間戳 int num maxn 樹上每個節點的初始值 int siz maxn siz u 表示以u為根的子樹的節點數 int top maxn ...

樹鏈剖分模板

點權模板 1 m a b c將節點a到節點b路徑上所有點都染成顏色c 2 q a b詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 如 112221 由3段組成 11 222 和 1 const int n 100100 struct edge g n 2 int cnt,head...