-
1 x y z
,表示将树从 xx 到 yy 结点最短路径上所有节点的值都加上 zz。 -
2 x y
,表示求树从 xx 到 yy 结点最短路径上所有节点的值之和。 -
3 x z
,表示将以 xx 为根节点的子树内所有节点值都加上 zz。 -
4 x
表示求以 xx 为根节点的子树内所有节点值之和
#include <bits/stdc++.h> using namespace std ; const int N=2e5+5,M=N; #define int long long int S,mod; int n,nxt[M],hd[N],all,go[M]; int dep[N],sz[N],fa[N],son[N]; int dfn[N],id[N],pool,top[N]; #define k1 k<<1 #define k2 k<<1|1 int a[N]; struct Tree{ int s,lazy; int l,r; }tr[N<<2]; void help(int k,int v){ tr[k].lazy+=v, tr[k].s+=v*(tr[k].r-tr[k].l+1); tr[k].lazy%=mod; tr[k].s%=mod; } void pushd(int k){ if(tr[k].lazy==0) return; help(k1,tr[k].lazy),help(k2,tr[k].lazy); tr[k].lazy=0; } int qry(int k,int x,int y){ int t=0; if(x<=tr[k].l&&y>=tr[k].r) return tr[k].s%mod; int md=(tr[k].l+tr[k].r)/2; pushd(k); if(x<=md) t+=qry(k1,x,y),t%=mod; if(y>md) t+=qry(k2,x,y),t%=mod; return t; } void add(int k,int x,int y,int z){ if(x<=tr[k].l&&y>=tr[k].r) return help(k,z); int md=(tr[k].l+tr[k].r)/2; pushd(k); if(x<=md) add(k1,x,y,z); if(y>md) add(k2,x,y,z); tr[k].s=tr[k1].s+tr[k2].s,tr[k].s%=mod; } void build(int k,int l,int r){ tr[k].l=l,tr[k].r=r; tr[k].s=0; if(l==r){ tr[k].s=a[id[l]]; tr[k].s%=mod; return; } int md=(l+r)/2; build(k1,l,md),build(k2,md+1,r); tr[k].s=tr[k1].s+tr[k2].s,tr[k].s%=mod; } void add(int x,int y){ go[++all]=y,nxt[all]=hd[x],hd[x]=all; } void dfs1(int x,int par){ fa[x]=par; sz[x]=1; dep[x]=dep[par]+1; son[x]=0; for(int i=hd[x];i;i=nxt[i]){ int y=go[i]; if(par==y) continue; dfs1(y,x); sz[x]+=sz[y]; if(sz[y]>sz[son[x]]) son[x]=y; } } void dfs2(int x,int topf){ dfn[x]=++pool; id[pool]=x; top[x]=topf; if(!son[x]) return ; dfs2(son[x],topf); for(int i=hd[x];i;i=nxt[i]){ int y=go[i]; if(y==fa[x]||y==son[x]) continue; dfs2(y,y); } } int qRange(int x,int y){ int res=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); res+=qry(1,dfn[top[x]],dfn[x]); res%=mod; x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); res+=qry(1,dfn[x],dfn[y]); res%=mod; return res; } void upRange(int x,int y,int z){ z%=mod; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); add(1,dfn[top[x]],dfn[x],z); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); add(1,dfn[x],dfn[y],z); } int qSon(int x){ return qry(1,dfn[x],dfn[x]+sz[x]-1)%mod; } void upSon(int x,int z){ z%=mod; add(1,dfn[x],dfn[x]+sz[x]-1,z); } signed main(){ int op,i,x,y,z,tes; cin>>n>>tes>>S>>mod; for(i=1;i<=n;i++) cin>>a[i]; for(i=1;i<n;i++) cin>>x>>y,add(x,y),add(y,x); dfs1(S,0); dfs2(S,S); build(1,1,n); while(tes--){ cin>>op; if(op==1){ cin>>x>>y>>z; upRange(x,y,z); } else if(op==2){ cin>>x>>y; cout<<qRange(x,y)<<endl; } else if(op==3){ cin>>x>>y; upSon(x,y); } else if(op==4){ cin>>x; cout<<qSon(x)<<endl; } } }