摘自部落格:
博主講得十分的清楚
以下是帶有注釋的**:
1/*2view code這是乙份自用的樹鏈剖分模板,
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 }
樹鏈剖分 模板
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...