樹鏈剖分詳情:跳轉大佬部落格:
解題心得:
個人看來其實樹鏈剖分就是把一棵標號沒有實際意義的樹重新標號,標號的規則按照重鏈優先,在有序之後用線段樹之類的資料結構來維護。
#include
using namespace std;
const
int maxn =
1e5+
100;
struct node node[maxn<<2]
;int num[maxn]
, n, m, rt, mod;
int size[maxn]
, deep[maxn]
, max_son[maxn]
, father[maxn]
, top[maxn]
, rk[maxn]
, id[maxn]
, cnt;
/* size[i] 代表以i為根節點的子樹的大小
deep[i] 代表節點i的深度
max_son[i] 代表以i的子節點為根節點的樹最大的子節點節點標號
father[i] 表示i的父親是誰
top[i] 代表i所在的重鏈的根節點
id[i] 代表標號為i的節點剖分之後的數
rk[i] 剖分之後數為i的節點的標號是多少
*/vector <
int> ve[maxn]
;void
init()
}int
dfs(
int pre,
int now,
int deep)}}
return size[now];}
void
dfs2
(int pre,
int now,
int top)}}
void
pushup
(int root)
void
push_down
(int root,
int l,
int r)
void
build_tree
(int root,
int l,
int r)
int mid = l + r >>1;
build_tree
(root<<
1, l, mid)
;build_tree
(root<<1|
1, mid+
1, r)
;pushup
(root);}
void
build_tree()
void
add(
int root,
int ql,
int qr,
int l,
int r,
int c)
push_down
(root, l, r)
;int mid = l + r >>1;
if(mid >= qr)
add(root<<
1, ql, qr, l, mid, c)
;else
if(mid < ql)
else
pushup
(root);}
void
update
(int l,
int r,
int c)
if(id[l]
> id[r]
)swap
(l, r)
;add(1
, id[l]
, id[r],1
, n, c);}
intquery
(int root,
int ql,
int qr,
int l,
int r)
push_down
(root, l, r)
;int mid = l + r >>1;
if(mid >= qr)
else
if(mid < ql)
else
}int
query
(int l,
int r)
if(id[l]
> id[r]
)swap
(l, r)
; sum +
=query(1
, id[l]
, id[r],1
, n)
;return sum % mod;
}int
main()
else
if(op ==2)
else
if(op ==3)
else
}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
題目描述 如題,已知一棵包含n個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作1 格式 1 x y z 表示將樹從x到y結點最短路徑上所有節點的值都加上z 操作2 格式 2 x y 表示求樹從x到y結點最短路徑上所有節點的值之和 操作3 格式 3 x z 表示將以x為根節點的子...