目录
- 代码答疑
重链剖分
- @ 2026-4-12 9:23:56
#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, m, rt, mod;
int hd[N], to[N << 1], nx[N << 1], ec;
int fa[N], dep[N], sz[N], son[N];//son[x] 重儿子的编号 , 没有重儿子 0
int top[N], dfn[N], rnk[N], tim;
long long a[N], b[N];
long long sum[N << 2], lz[N << 2];
void add(int x, int y){
to[++ec] = y;
nx[ec] = hd[x];
hd[x] = ec;
}
// fa dep sz son
void dfs1(int x, int f){
fa[x] = f;
dep[x] = dep[f] + 1;
sz[x] = 1;
for(int i = hd[x]; i; i = nx[i]){
int y = to[i];
if(y == f) continue;
dfs1(y, x);
sz[x] += sz[y];
if(sz[y] > sz[son[x]]) son[x] = y;
}
}
//top dfn rnk
void dfs2(int x, int tp){
top[x] = tp;
dfn[x] = ++tim;
rnk[tim] = x;//反向记录
b[tim] = a[x] % mod;
if(son[x]) dfs2(son[x], tp);//优先走重儿子
for(int i = hd[x]; i; i = nx[i]){
int y = to[i];
if(y == fa[x] || y == son[x]) continue;
dfs2(y, y);//轻儿子作为新链头
}
}
void up(int p){
sum[p] = (sum[p << 1] + sum[p << 1 | 1]) % mod;
}
void tag(int p, int l, int r, long long v){
v %= mod;
sum[p] = (sum[p] + (r - l + 1) * v) % mod;
lz[p] = (lz[p] + v) % mod;
}
void down(int p, int l, int r){
if(!lz[p]) return;
int mid = (l + r) >> 1;
tag(p << 1, l, mid, lz[p]);
tag(p << 1 | 1, mid + 1, r, lz[p]);
lz[p] = 0;
}
void build(int p, int l, int r){
if(l == r){
sum[p] = b[l] % mod;
return;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
up(p);
}
void chg(int p, int l, int r, int x, int y, long long v){
if(x <= l && r <= y){
tag(p, l, r, v);
return;
}
down(p, l, r);
int mid = (l + r) >> 1;
if(x <= mid) chg(p << 1, l, mid, x, y, v);
if(y > mid) chg(p << 1 | 1, mid + 1, r, x, y, v);
up(p);
}
long long ask(int p, int l, int r, int x, int y){
if(x <= l && r <= y) return sum[p] % mod;
down(p, l, r);
int mid = (l + r) >> 1;
long long res = 0;
if(x <= mid) res = (res + ask(p << 1, l, mid, x, y)) % mod;
if(y > mid) res = (res + ask(p << 1 | 1, mid + 1, r, x, y)) % mod;
return res % mod;
}
void chg1(int x, int y, long long v){
v %= mod;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
chg(1, 1, n, dfn[top[x]], dfn[x], v);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
chg(1, 1, n, dfn[x], dfn[y], v);
}
long long ask1(int x, int y){
long long res = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
res = (res + ask(1, 1, n, dfn[top[x]], dfn[x])) % mod;
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
res = (res + ask(1, 1, n, dfn[x], dfn[y])) % mod;
return res % mod;
}
void chg2(int x, long long v){
v %= mod;
chg(1, 1, n, dfn[x], dfn[x] + sz[x] - 1, v);
}
long long ask2(int x){
return ask(1, 1, n, dfn[x], dfn[x] + sz[x] - 1) % mod;
}
int main(){
cin >> n >> m >> rt >> mod;
for(int i = 1; i <= n; i++){
cin >> a[i];
a[i] %= mod;
}
for(int i = 1; i < n; i++){
int x, y;
cin >> x >> y;
add(x, y);
add(y, x);
}
dfs1(rt, 0);
dfs2(rt, rt);
build(1, 1, n);
while(m--){
int op;
cin >> op;
if(op == 1){
int x, y;
long long z;
cin >> x >> y >> z;
chg1(x, y, z);
}
else if(op == 2){
int x, y;
cin >> x >> y;
cout << ask1(x, y) % mod << '\n';
}
else if(op == 3){
int x;
long long z;
cin >> x >> z;
chg2(x, z);
}
else{
int x;
cin >> x;
cout << ask2(x) % mod << '\n';
}
}
return 0;
}
0 条评论
目前还没有评论...
京公网安备11010802045784号
YIZHIYANG 一只羊 LV 10