#include#include#include
#include
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
using
namespace
std;
const
int maxn = 500100
;int
p;typedef
long
long
ll;struct
edge edges[maxn*2
];int
head[maxn], tot;
intn;
ll w[maxn];
intfa[maxn], son[maxn], siz[maxn], dep[maxn];
inttop[maxn], id[maxn], rk[maxn], cnt;
//son[u]: u的重兒子
//top[u]: u所在鏈的頂端節點
////
id[u]: 樹鏈剖分後節點的新編號
//rk[u]: dfs編號對應的節點 rk[id[u]] = u
//cnt : dfs序
void add(int u, int
v) //
求fa, siz, dep, son
void dfs1(int
u) }
//連線重鏈
void dfs2(int u, int
topf) }/*
操作1: 格式: 1 x y z 表示將樹從x到y結點最短路徑上所有節點的值都加上z
操作2: 格式: 2 x y 表示求樹從x到y結點最短路徑上所有節點的值之和
操作3: 格式: 3 x z 表示將以x為根節點的子樹內所有節點值都加上z
操作4: 格式: 4 x 表示求以x為根節點的子樹內所有節點值之和 */
ll sum[maxn*4], lazy[maxn*4
];void build(int rt, int l, int
r)
else
}void pushdown(int rt, int
len)
}void update(int rt, int l, int r, int l, int
r, ll add)
int mid = (l+r)/2
; pushdown(rt, r-l+1
);
if(l<=mid)
update(lson, l, r, add);
if(r>mid)
update(rson, l, r, add);
sum[rt] = (sum[rt<<1] + sum[rt<<1|1]) %p;
}ll query(
int rt, int l, int r, int l, int
r) //
操作1void updatepath(int x, int
y, ll z)
if(dep[x]>dep[y]) swap(x, y);
update(
1, 1
, n, id[x], id[y], z);}//
操作3void updateson(int
x, ll z)
//操作2
ll querypath(int x, int
y)
if(dep[x]>dep[y]) swap(x, y);
res = (res + query(1, 1, n, id[x], id[y])) %p;
return
res;}//
操作4ll qeuryson(int
x) int
main()
for(int i=0;i1;i++)
dfs1(r);
dfs2(r, r);
build(
1, 1
, n);
while(m--)
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 模板 樹鏈剖分
樹鏈剖分詳情 跳轉大佬部落格 解題心得 個人看來其實樹鏈剖分就是把一棵標號沒有實際意義的樹重新標號,標號的規則按照重鏈優先,在有序之後用線段樹之類的資料結構來維護。include using namespace std const int maxn 1e5 100 struct node node ...