Luogu_ P3384 【模板】轻重链剖分
#include <bits/stdc++.h> using namespace std; #define ll long long struct tree{ll v,late;}t[100010<<2]; int n,m,r,mod,val[100010],p[100010],size[100010],deep[100010],son[100010],top[100010]; int dfn[100010],tot,id[100010],cnt[100010]; vector<int> G[100010]; void make_tree(int u,int fa){ size[u]=1; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa)continue; p[v]=u; deep[v]=deep[u]+1; make_tree(v,u); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; } } void make_son(int u,int fa){ top[u]=fa; dfn[u]=++tot; id[tot]=u; if(son[u])make_son(son[u],fa); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=p[u] && v!=son[u])make_son(v,v); } cnt[u]=tot; } void build_tree(int o,int l,int r){ if(l==r){t[o].v=val[id[l]]; return;} int mid=l+r>>1; build_tree(o<<1,l,mid); build_tree(o<<1|1,mid+1,r); t[o].v=t[o<<1].v+t[o<<1|1].v; } void push_down(int o,int l,int r){ t[o<<1].late+=t[o].late; t[o<<1|1].late+=t[o].late; int mid=l+r>>1; t[o<<1].v+=t[o].late*(mid-l+1); t[o<<1|1].v+=t[o].late*(r-mid); t[o].late=0; } void update(int o,int l,int r,int L,int R,int v){ if(L<=l && r<=R){ t[o].late+=v; t[o].v+=(r-l+1)*v; return; } if(t[o].late)push_down(o,l,r); ll mid=l+r>>1; if(mid>=L)update(o<<1,l,mid,L,R,v); if(mid<R)update(o<<1|1,mid+1,r,L,R,v); t[o].v=t[o<<1].v+t[o<<1|1].v; } ll quire(int o,int l,int r,int L,int R){ if(L<=l && r<=R)return t[o].v; if(t[o].late)push_down(o,l,r); int mid=l+r>>1; ll ans=0; if(L<=mid)ans+=quire(o<<1,l,mid,L,R); if(mid<R)ans+=quire(o<<1|1,mid+1,r,L,R); return ans; } void add(){ int x,y,z; scanf("%d%d%d",&x,&y,&z); while(top[x]!=top[y]){ if(deep[top[y]]>deep[top[x]])swap(x,y); update(1,1,tot,dfn[top[x]],dfn[x],z); x=p[top[x]]; } if(deep[y]>deep[x])swap(x,y); update(1,1,tot,dfn[y],dfn[x],z); } void get_answer(){ int x,y; ll ans=0; scanf("%d%d",&x,&y); while(top[x]!=top[y]){ if(deep[top[y]]>deep[top[x]])swap(x,y); ans+=quire(1,1,tot,dfn[top[x]],dfn[x]); ans%=mod; x=p[top[x]]; } if(deep[y]>deep[x])swap(x,y); ans+=quire(1,1,tot,dfn[y],dfn[x]); printf("%lld\n",ans%mod); } void add_son(){ int x,z; scanf("%d%d",&x,&z); update(1,1,tot,dfn[x],cnt[x],z); } void get_son(){ int x; scanf("%d",&x); ll ans=quire(1,1,tot,dfn[x],cnt[x]); printf("%lld\n",ans%mod); } int main(){ scanf("%d%d%d%d",&n,&m,&r,&mod); for(int i=1;i<=n;i++)scanf("%d",&val[i]); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } p[r]=r; make_tree(r,r); make_son(r,r); build_tree(1,1,tot); while(m--){ int q; scanf("%d",&q); if(q==1)add(); if(q==2)get_answer(); if(q==3)add_son(); if(q==4)get_son(); } return 0; }