样例过了,WA 1个点,RE 9个点
#include <bits/stdc++.h>
using namespace std;
long long n,m,mod,cnt,ans,num,root,sz[200002],val[200002],dep[200002],head[200002];
long long v[200002],id[200002],end[200002],top[200002],son[200002],fat[200002];
struct edge{
int nxt,to;
}e[300002];
struct node{
int lazy,sum;
}a[500002];
void addedge(int A,int B) {
e[++cnt].to=B;
e[cnt].nxt=head[A];
head[A]=cnt;
}
void dfs1(int u,int last) {
sz[u]=1;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].to;
if(v==last) continue;
fat[v]=u;
dep[v]=dep[u]+1;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>=sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int last,int rt) {
++num;
top[u]=rt;
id[u]=num;
if(!son[u]) return;
dfs2(son[u],u,rt);
end[son[u]]=num;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].to;
if(v==last || v==son[u]) continue;
dfs2(v,u,v);
end[v]=num;
}
}
void pushup(int num) {
a[num].sum=(a[num*2].sum+a[num*2+1].sum)%mod;
}
void pushdown(int num,int l,int r) {
if(!a[num].lazy)return;
a[num*2].lazy+=a[num].lazy;
a[num*2+1].lazy+=a[num].lazy;
a[num*2].lazy%=mod;
a[num*2+1].lazy%=mod;
int len;
len=r-l+1;
a[num*2].sum+=(len-(len>>1))*a[num].lazy;
a[num*2+1].sum+=(len>>1)*a[num].lazy;
a[num*2].sum%=mod;
a[num*2+1].sum%=mod;
a[num].lazy=0;
}
void build(int num,int l,int r) {
if(l==r) {
a[num].sum=v[l]%mod;
return ;
}
int mid=(l+r)/2;
build(num*2,l,mid);
build(num*2+1,mid+1,r);
pushup(num);
}
void update(int num,int l,int r,int ll,int rr,int x) {
if(l>rr || ll>r) return ;
if(ll<=l && r<=rr) {
a[num].lazy+=x;
a[num].sum+=((r-l+1)*x);
return ;
}
pushdown(num,l,r);
int mid=(l+r)/2;
update(num*2,l,mid,ll,rr,x);
update(num*2+1,mid+1,r,ll,rr,x);
pushup(num);
}
long long query(int num,int l,int r,int ll,int rr) {
if(l>rr || ll>r) return 0;
if(ll<=l && rr<=r) return a[num].sum;
pushdown(num,l,r);
int mid=(l+r)/2;
if(rr<=mid) return query(num*2,l,mid,ll,rr);
if(ll>mid) return query(num*2+1,mid+1,r,ll,rr);
return query(num*2,l,mid,ll,rr)+query(num*2+1,mid+1,r,ll,rr);
}
void lca(int x,int y,int z) {
z%=mod;
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
if(z) update(1,1,n,id[top[x]],id[x],z);
else ans+=query(1,1,n,id[top[x]],id[x]);
x=fat[top[x]];
ans%=mod;
}
if(dep[x]>dep[y]) swap(x,y);
if(z) update(1,1,n,id[x],id[y],z);
else ans+=query(1,1,n,id[x],id[y]);
ans%=mod;
}
signed main() {
scanf("%lld%lld%lld%lld",&n,&m,&root,&mod);
for(int i=1;i<=n;i++) scanf("%lld",&val[i]);
for(int i=1;i<=n-1;i++) {
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs1((int)root,0);
dfs2((int)root,0,root);
end[root]=num;
for(int i=1;i<=n;i++) v[id[i]]=val[i];
build(1,1,n);
while(m--) {
int op,x,y,z;
scanf("%d",&op);
if(op==1) {
scanf("%d%d%d",&x,&y,&z);
lca(x,y,z);
}
if(op==2) {
scanf("%d%d",&x,&y);
ans=0;
lca(x,y,0);
printf("%lld\n",ans%mod);
}
if(op==3) {
scanf("%d%d",&x,&y);
update(1,1,(int)n,(int)id[x],(int)id[x]+sz[x]-1,y);
}
if(op==4) {
scanf("%d",&x);
printf("%lld\n",query(1,1,(int)n,(int)id[x],(int)id[x]+sz[x]-1)%mod);
}
}
return 0;
}