树链剖分
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n, m, r, p, w[N];
int tot, h[N], e[2*N], nxt[2*N];
void add(int u, int v){
nxt[++tot] = h[u];
h[u] = tot;
e[tot] = v;
}
struct Node{
int l, r, lazy, sum;
} tr[4*N];
void pushup(int u){
tr[u].sum = (tr[u<<1].sum + tr[u<<1|1].sum) % p;
}
void pushdown(int u){
if(tr[u].lazy){
tr[u<<1].lazy = (tr[u<<1].lazy + tr[u].lazy) % p;
tr[u<<1].sum = (tr[u<<1].sum + 1ll*tr[u].lazy * (tr[u<<1].r - tr[u<<1].l + 1)) % p;
tr[u<<1|1].lazy = (tr[u<<1|1].lazy + tr[u].lazy) % p;
tr[u<<1|1].sum = (tr[u<<1|1].sum + 1ll*tr[u].lazy * (tr[u<<1|1].r - tr[u<<1|1].l + 1)) % p;
tr[u].lazy = 0;
}
}
void build(int u, int l, int r){
tr[u].l = l;
tr[u].r = r;
if(l == r) return ;
int mid = (l+r)>>1;
build(u<<1, l, mid);
build(u<<1|1, mid+1, r);
}
void modify(int u, int L, int R, int val){
int l = tr[u].l, r = tr[u].r;
if(l >= L && r <= R){
tr[u].lazy = (tr[u].lazy+val)%p;
tr[u].sum = (tr[u].sum + 1ll*val*(r-l+1))%p;
return ;
}
if(tr[u].lazy) pushdown(u);
int mid = (l+r)>>1;
if(mid >= L) modify(u<<1, L, R, val);
if(mid+1 <= R) modify(u<<1|1, L, R, val);
pushup(u);
}
int query(int u, int L, int R){
if(tr[u].lazy) pushdown(u);
int l = tr[u].l, r = tr[u].r;
if(l >= L && r <= R) return tr[u].sum;
int ans = 0, mid = (l+r)>>1;
if(mid >= L) ans = (ans + query(u<<1, L, R)) % p;
if(mid+1 <= R) ans = (ans + query(u<<1|1, L, R)) % p;
return ans;
}
int f[N], son[N], siz[N], deep[N];
void dfs1(int u){
siz[u] = 1;
int mx = 0;
for(int i = h[u]; i; i = nxt[i]){
int v = e[i];
if(v == f[u]) continue;
f[v] = u;
deep[v] = deep[u]+1;
dfs1(v);
if(siz[v] > mx) mx = siz[v], son[u] = v;
siz[u] += siz[v];
}
}
int top[N], dfn[N], idx;
void dfs2(int u){
dfn[u] = ++idx;
if(!son[u]) return ;
top[son[u]] = top[u];
dfs2(son[u]);
for(int i = h[u]; i; i = nxt[i]){
int v = e[i];
if(dfn[v]) continue;
top[v] = v;
dfs2(v);
}
}
void add_path(int x, int y, int val){
while(top[x] != top[y]){
if(deep[top[x]] < deep[top[y]]) swap(x, y);
modify(1, dfn[top[x]], dfn[x], val);
x = f[top[x]];
}
if(deep[x] > deep[y]) swap(x, y);
modify(1, dfn[x], dfn[y], val);
}
int ask_path(int x, int y){
int ans = 0;
while(top[x] != top[y]){
if(deep[top[x]] < deep[top[y]]) swap(x, y);
ans = (ans+query(1, dfn[top[x]], dfn[x])) % p;
x = f[top[x]];
}
if(deep[x] > deep[y]) swap(x, y);
ans = (ans+query(1, dfn[x], dfn[y])) % p;
return ans;
}
void add_tree(int x, int val){
modify(1, dfn[x], dfn[x]+siz[x]-1, val);
}
int ask_tree(int x){
return query(1, dfn[x], dfn[x]+siz[x]-1);
}
int main(){
scanf("%d%d%d%d", &n, &m, &r, &p);
build(1, 1, n);
for(int i = 1; i <= n; i++) scanf("%d", &w[i]);
for(int i = 1; i < n; i++){
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
dfs1(r);
dfs2(r);
for(int i = 1; i <= n; i++) modify(1, dfn[i], dfn[i], w[i]);
while(m--){
int opt, x, y, z;
scanf("%d", &opt);
if(opt == 1){
scanf("%d%d%d", &x, &y, &z);
add_path(x, y, z);
}else if(opt == 2){
scanf("%d%d", &x, &y);
printf("%d\n", ask_path(x, y));
}else if(opt == 3){
scanf("%d%d", &x, &z);
add_tree(x, z);
}else{
scanf("%d", &x);
printf("%d\n", ask_tree(x));
}
}
return 0;
}
树剖+线段树, P3384

浙公网安备 33010602011771号