RT,在 #2 RE了
#include<bits/stdc++.h>
#define MAXN 100002
#define ls(x) 2*x
#define rs(x) 2*x+1
using namespace std;
inline int read()
{
int f=1,w=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
return f*w;
}
int n,m,r,mod;
vector<int>V[MAXN];
int siz[MAXN],dep[MAXN],fa[MAXN],son[MAXN],w[MAXN],a[MAXN],top[MAXN],dfn[MAXN],num;
int tr[MAXN],tag[MAXN];
void add(int x,int y)
{
V[x].push_back(y);
return;
}
void dfs1(int now,int f,int deep)
{
dep[now]=deep;
fa[now]=f;
siz[now]=1;
int son_siz=-1;
for(int i:V[now])
{
int t=i;
if(t==f)continue;
dfs1(t,now,deep+1);
siz[now]+=siz[t];
if(siz[t]>son_siz)son[now]=t,son_siz=siz[t];
}
return;
}
void dfs2(int now,int topn)
{
dfn[now]=++num;
w[num]=a[now];
top[now]=topn;
if(!son[now])return;
dfs2(son[now],topn);
for(int i:V[now])
{
int t=i;
if(t==fa[now]||t==son[now])continue;
dfs2(t,t);
}
}
void push_up(int p)
{
tr[p]=(tr[ls(p)]+tr[rs(p)])%mod;
}
void addtag(int l,int r,int p,int k)
{
tr[p]+=(r-l+1)*k;
tag[p]+=k;
tr[p]%=mod;
tag[p]%=mod;
}
void push_down(int l,int r,int p)
{
if(tag[p])
{
int mid=(l+r)>>1;
addtag(l,mid,ls(p),tag[p]);
addtag(mid+1,r,rs(p),tag[p]);
tag[p]=0;
}
}
void build(int l,int r,int p)
{
if(l==r)
{
tr[p]=w[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,ls(p));build(mid+1,r,rs(p));
push_up(p);
}
void update(int l,int r,int s,int t,int p,int k)
{
k%=mod;
if(s>=l&&t<=r)
{
addtag(s,t,p,k);
return;
}
push_down(s,t,p);
int mid=(s+t)>>1;
if(mid>=l)update(l,r,s,mid,ls(p),k);
if(mid<r)update(l,r,mid+1,t,rs(p),k);
push_up(p);
return;
}
int query(int l,int r,int s,int t,int p)
{
if(s>=l&&t<=r)
return tr[p]%mod;
push_down(s,t,p);
int mid=(s+t)>>1,sum=0;
if(mid>=l)sum+=query(l,r,s,mid,ls(p));
if(mid<r)sum+=query(l,r,mid+1,t,rs(p));
return sum%mod;
}
int ask_range(int s,int t)
{
int ans=0;
while(top[s]!=top[t])
{
if(dep[top[s]]<dep[top[t]])swap(s,t);
ans+=query(dfn[top[s]],dfn[s],1,n,1);
ans%=mod;
s=fa[top[s]];
}
if(dep[s]>dep[t])swap(s,t);
ans+=query(dfn[s],dfn[t],1,n,1);
return ans;
}
int ask_son(int s)
{
return query(dfn[s],dfn[s]+siz[s]-1,1,n,1);
}
void upd_range(int s,int t,int k)
{
k%=mod;
while(top[s]!=top[t])
{
if(dep[top[s]]<dep[top[t]])swap(s,t);
update(dfn[top[s]],dfn[s],1,n,1,k);
s=fa[top[s]];
}
if(dep[s]>dep[t])swap(s,t);
update(dfn[s],dfn[t],1,n,1,k);
return;
}
void upd_son(int s,int k)
{
k%=mod;
update(dfn[s],dfn[s]+siz[s]-1,1,n,1,k);
return;
}
int main()
{
freopen("P3384_2.in","r",stdin);
freopen("a.out","w",stdout);
n=read(),m=read(),r=read(),mod=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,n,1);
for(int i=1;i<=m;i++)
{
int opt=read(),x=read(),y,z;
switch(opt)
{
case 1:
y=read(),z=read();
upd_range(x,y,z);
break;
case 2:
y=read();
cout<<ask_range(x,y)<<endl;
break;
case 3:
z=read();
upd_son(x,z);
break;
case 4:
cout<<ask_son(x)<<endl;
break;
default:
break;
}
}
return 0;
}