OI模板 树链剖分
重链剖分-查、改路径、子树点权
const int N = 1;
int Son[N], Nid[N], cnt, Fa[N], Dep[N], Siz[N], Top[N];
int Wegt[N], Nwet[N], Head[N], Edge[N], Next[N], tot;
struct Node{ int sum, lazy, l, r; } T[N*4];
int n, m, rt, mod;
void addedge(int u, int v){
Edge[++tot] = v, Next[tot] = Head[u], Head[u] = tot;
}
void update(int p){
T[p].sum = (T[p<<1].sum + T[p<<1|1].sum) % mod;
}
void spread(int p){
if(T[p].lazy){
T[p<<1].sum += T[p].lazy * (T[p<<1].r - T[p<<1].l + 1);
T[p<<1|1].sum += T[p].lazy * (T[p<<1|1].r - T[p<<1|1].l + 1);
T[p<<1].lazy += T[p].lazy;
T[p<<1|1].lazy += T[p].lazy;
T[p].lazy = 0;
}
}
void buildtree(int p, int l, int r){
T[p].l = l, T[p].r = r;
if(l == r){ T[p].sum = Nwet[l] % mod; return; }
int mid = l + r >> 1;
buildtree(p << 1, l, mid);
buildtree(p << 1 | 1, mid + 1, r);
update(p);
}
void change(int p, int l, int r, int v){
if(l <= T[p].l && T[p].r <= r){
T[p].sum = (T[p].sum + v * (T[p].r - T[p].l + 1)) % mod;
T[p].lazy += v;
} else {
int mid = T[p].l + T[p].r >> 1;
spread(p);
if(l <= mid) change(p << 1, l, r, v);
if(mid < r) change(p << 1 | 1, l, r, v);
update(p);
}
}
int query(int p, int l, int r){
if(l <= T[p].l && T[p].r <= r) return T[p].sum % mod;
int mid = T[p].l + T[p].r >> 1, res = 0;
spread(p);
if(l <= mid) res = (res + query(p << 1, l, r)) % mod;
if(mid < r) res = (res + query(p << 1 | 1, l, r)) % mod;
return res;
}
void dfs1(int x, int fa){
Dep[x] = Dep[fa] + 1, Fa[x] = fa, Siz[x] = 1;
int maxson = -1;
for(int i = Head[x]; i; i = Next[i]){
int y = Edge[i];
if(y == fa) continue;
dfs1(y, x);
Siz[x] += Siz[y];
if(Siz[y] > maxson) Son[x] = y, maxson = Siz[y];
}
}
void dfs2(int x, int top){
Nid[x] = ++ cnt, Nwet[cnt] = Wegt[x], Top[x] = top;
if(!Son[x]) return;
dfs2(Son[x], top);
for(int i = Head[x]; i; i = Next[i]){
int y = Edge[i];
if(y == Fa[x] || y == Son[x]) continue;
dfs2(y, y);
}
}
void Init(){
dfs1(rt, 0), dfs2(rt, rt);
buildtree(1, 1, n);
}
void UpdateRange(int x, int y, int k){
k %= mod;
while(Top[x] != Top[y]){
if(Dep[Top[x]] < Dep[Top[y]]) swap(x, y);
change(1, Nid[Top[x]], Nid[x], k);
x = Fa[Top[x]];
}
if(Dep[x] > Dep[y]) swap(x, y);
change(1, Nid[x], Nid[y], k);
}
int QueryRange(int x, int y){
int ans = 0;
while(Top[x] != Top[y]){
if(Dep[Top[x]] < Dep[Top[y]]) swap(x, y);
ans = (ans + query(1, Nid[Top[x]], Nid[x])) % mod;
x = Fa[Top[x]];
}
if(Dep[x] > Dep[y]) swap(x, y);
return (ans + query(1, Nid[x], Nid[y])) % mod;
}
void UpdateSon(int x, int k){
change(1, Nid[x], Nid[x] + Siz[x] - 1, k);
}
int QuerySon(int x){
return query(1, Nid[x], Nid[x] + Siz[x] - 1);
}
例题:Luogu P3384 【模板】轻重链剖分/树链剖分。