樹鏈剖分大致是將樹劃分為若干條輕重邊和輕重鏈,其中關鍵的是重鏈和輕邊;
每次dfs先走重兒子(所在子樹點數多),對生成的dfs序建立線段樹維護;
該序列滿足重鏈在其中連續,子樹在其中連續;
對於鏈的操作,將兩端點不斷沿著重鏈向上走,最終走到同一條鏈,然後便可完成操作;
對於子樹的操作,記錄子樹大小,直接用線段樹維護即可。
#include
#include
using
namespace std;
inline
intread()
const
int maxn =
1e5+5;
int head[maxn]
, eid;
struct edge edge[
2* maxn]
;inline
void
insert
(int u,
int v)
int n, m, r, mod, a[maxn]
;int f[maxn]
, depth[maxn]
, size[maxn]
, best[maxn]
;int seq[maxn]
, order[maxn]
, cnt, first[maxn]
;void
dfs1
(int u,
int fa)
}void
dfs2
(int u,
int h)
}struct st t[
4* maxn]
;inline
voidup(
int p)
inline
void
mark
(int p,
int d)
inline
void
down
(int p)
}void
build
(int p,
int l,
int r)
int mid =
(l + r)
>>1;
build(2
* p, l, mid)
;build(2
* p +
1, mid +
1, r);up
(p);
}void
modify
(int p,
int x,
int y,
int d)
down
(p);
int mid =
(t[p]
.l + t[p]
.r)>>1;
if(x <= mid)
modify(2
* p, x, y, d);if
(y > mid)
modify(2
* p +
1, x, y, d);up
(p);
}int
query
(int p,
int x,
int y)
inline
void
modify0
(int p1,
int p2,
int d)
if(depth[p1]
> depth[p2]
)swap
(p1, p2)
;modify(1
, order[p1]
, order[p2]
, d);}
inline
intquery0
(int p1,
int p2)
if(depth[p1]
> depth[p2]
)swap
(p1, p2)
; ret =
(ret +
query(1
, order[p1]
, order[p2]))
% mod;
return ret;
}int
main()
dfs1
(r,0);
dfs2
(r, r)
;build(1
,1, n)
;while
(m--)}
return0;
}
洛谷 P3384 模板 樹鏈剖分
如題,已知一棵包含n個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作1 格式 1 x y z 表示將樹從x到y結點最短路徑上所有節點的值都加上z 操作2 格式 2 x y 表示求樹從x到y結點最短路徑上所有節點的值之和 操作3 格式 3 x z 表示將以x為根節點的子樹內所有節...
P3384 模板 樹鏈剖分 洛谷
題目鏈結 如題,已知一棵包含n個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作1 格式 1 x y z 表示將樹從x到y結點最短路徑上所有節點的值都加上z 操作2 格式 2 x y 表示求樹從x到y結點最短路徑上所有節點的值之和 操作3 格式 3 x z 表示將以x為根節點的子...
洛谷 P3384 模板 樹鏈剖分
樹鏈剖分詳情 跳轉大佬部落格 解題心得 個人看來其實樹鏈剖分就是把一棵標號沒有實際意義的樹重新標號,標號的規則按照重鏈優先,在有序之後用線段樹之類的資料結構來維護。include using namespace std const int maxn 1e5 100 struct node node ...