#include <iostream> #include <iomanip> #include <cstdio> #include <cstdlib> #include <string> #include <cstring> #include <cmath> #include <cctype> #include <algorithm> #include <queue> #include <stack> using namespace std; typedef long long LL; struct edge { int ed,next; } E[int(1e6)+10]; int head[100100],Ecnt; int N,M,R,P; LL a[100100]; struct node { LL sum,atag; } T[100100<<3]; LL real[100010],sid[100010],hson[100010],fa[100010],dep[100010],size[100010],top[100010]; LL tot; void addEdge(int st,int ed) { E[++Ecnt].ed=ed; E[Ecnt].next=head[st]; head[st]=Ecnt; } void dfs1(int st) { size[st]=1; for(int i=head[st]; i; i=E[i].next) { int ed=E[i].ed; if(fa[st]!=ed) { dep[ed]=dep[st]+1; fa[ed]=st; dfs1(ed); if(hson[st]==0||size[hson[st]]<size[ed]) hson[st]=ed; size[st]+=size[ed]; } } } void dfs2(int st,int anc) { top[st]=anc; sid[st]=++tot; real[tot]=st; if(hson[st]==0) return; dfs2(hson[st],anc); for(int i=head[st]; i; i=E[i].next) { int ed=E[i].ed; if(ed!=fa[st]&&ed!=hson[st]) dfs2(ed,ed); } } void pushup(int id) { T[id].sum=T[id<<1].sum+T[id<<1|1].sum; } void pushdown(int L,int R,int id) { if(T[id].atag) { if(L!=R) { T[id<<1].atag+=T[id].atag; T[id<<1|1].atag+=T[id].atag; } T[id].sum+=(R-L+1)*T[id].atag; T[id].atag=0; } } void build_tree(int L,int R,int id) { if(L==R) { T[id].sum=a[real[L]]; return; } int mid=(L+R)/2; build_tree(L,mid,id<<1); build_tree(mid+1,R,id<<1|1); pushup(id); } void modify(int B,int E,int x,int L,int R,int id) { if(L>E||R<B) return; pushdown(L,R,id); if(L>=B&&R<=E) { T[id].atag+=x; return; } int mid=(L+R)>>1; modify(B,E,x,L,mid,id<<1); modify(B,E,x,mid+1,R,id<<1|1); pushdown(L,mid,id<<1); pushdown(mid+1,R,id<<1|1); pushup(id); } LL query(int B,int E,int L,int R,int id) { if(L>E||R<B) return 0ll; pushdown(L,R,id); if(L>=B&&R<=E) return T[id].sum%P; int mid=(L+R)>>1; return query(B,E,L,mid,id<<1)+query(B,E,mid+1,R,id<<1|1); } void tree_add() { LL x,v; scanf("%lld%lld",&x,&v); modify(sid[x],sid[x]+size[x]-1,v,1,N,1); } void tree_query() { LL x; scanf("%lld",&x); printf("%lld\n",query(sid[x],sid[x]+size[x]-1,1,N,1)%P); } void chain_add() { LL u,v,w,tu,tv; scanf("%lld%lld%lld",&u,&v,&w); tu=top[u],tv=top[v]; while(tu!=tv) { if(dep[tu]<dep[tv]) { swap(tu,tv); swap(u,v); } modify(sid[tu],sid[u],w,1,N,1); u=fa[tu]; tu=top[u]; } if(dep[u]<dep[v]) swap(u,v); modify(sid[v],sid[u],w,1,N,1); } void chain_query() { LL u,v,tu,tv,ret=0; scanf("%lld%lld",&u,&v); tu=top[u],tv=top[v]; while(tu!=tv) { if(dep[tu]<dep[tv]) { swap(tu,tv); swap(u,v); } LL t=query(sid[tu],sid[u],1,N,1); ret+=query(sid[tu],sid[u],1,N,1); ret%=P; u=fa[tu]; tu=top[u]; } if(dep[u]<dep[v]) swap(u,v); LL t=query(sid[v],sid[u],1,N,1); ret+=t; printf("%lld\n",ret%P); } void init(); int main() { init(); for(int i=1;i<=M;++i) { int q; scanf("%d",&q); switch(q) { case 4:tree_query();break; case 3:tree_add();break; case 2:chain_query();break; case 1:chain_add();break; } } return 0; } void init() { scanf("%d%d%d%d",&N,&M,&R,&P); for(int i=1; i<=N; ++i) scanf("%lld",a+i); for(int i=1; i<=N-1; ++i) { int x,y; scanf("%d%d",&x,&y); addEdge(x,y); addEdge(y,x); } dep[R]=1; dfs1(R); dfs2(R,R); build_tree(1,N,1); }
|