#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+10;
int mo,cx=0;
struct node{
int val;
vector<int> lj;
int spson;
int size;
int top;
int dep;
int df;
int fa;
};
node tr[maxn];
int xds[maxn];
void dfs1(int x,int fa,int dd)
{
tr[x].dep=dd;
tr[x].size=1;
tr[x].spson=-1;
tr[x].fa=fa;
int ss=tr[x].lj.size();
for(int i=0;i<ss;i++)
{
int sx=tr[x].lj[i];
if(sx!=fa)
{
dfs1(sx,x,dd+1);
tr[x].size+=tr[sx].size;
if(tr[x].spson==-1||tr[sx].size>tr[tr[x].spson].size)
tr[x].spson=sx;
}
}
}
void dfs2(int x,int fa)
{
if(x==tr[fa].spson)
tr[x].top=tr[fa].top;
else
tr[x].top=x;
tr[x].df=++cx;
if(tr[x].spson!=-1)
dfs2(tr[x].spson,x);
int ss=tr[x].lj.size();
for(int i=0;i<ss;i++)
{
int sx=tr[x].lj[i];
if(sx!=fa&&sx!=tr[x].spson)
{
dfs2(sx,x);
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
struct xdds{
int left;
int right;
int ans;
int lazy;
};
xdds trr[4*maxn];
void build(int le,int ri,int x)
{
trr[x].lazy=0;
trr[x].left=le;
trr[x].right=ri;
if(le==ri)
{
trr[x].ans=xds[le];
return;
}
int mid=(le+ri)/2;
build(le,mid,2*x);
build(mid+1,ri,2*x+1);
trr[x].ans=trr[2*x].ans+trr[2*x+1].ans;
return;
}
void push(int rt)
{
int k=trr[rt].lazy%mo;
trr[rt].lazy=0;
int le=rt*2,ri=rt*2+1;
trr[le].lazy+=k,trr[ri].lazy+=k;
trr[le].ans=(trr[le].ans+k*(trr[le].right-trr[le].left+1))%mo;
trr[ri].ans=(trr[ri].ans+k*(trr[ri].right-trr[ri].left+1))%mo;
}
void xiug(int x,int y,int k,int rt)
{
if(x>y) return;
if(x<=trr[rt].left&&trr[rt].right<=y)
{
trr[rt].lazy=(trr[rt].lazy+k)%mo;
trr[rt].ans=(trr[rt].ans+k*(trr[rt].right-trr[rt].left+1))%mo;
return;
}
//cout<<x<<' '<<y<<endl;
push(rt);
int mid=(trr[rt].left+trr[rt].right)/2;
if(x<=mid)
xiug(x,y,k,2*rt);
if(y>=mid+1)
xiug(x,y,k,2*rt+1);
trr[rt].ans=trr[2*rt].ans+trr[2*rt+1].ans;
trr[rt].ans=trr[rt].ans%mo;
return;
}
int js(int x,int y,int rt)
{
int ans=0;
if(x>y) return 0;
if(x<=trr[rt].left&&trr[rt].right<=y)
{
return trr[rt].ans%mo;
}
push(rt);
int mid=(trr[rt].left+trr[rt].right)/2;
if(x<=mid)
ans=(ans+js(x,y,2*rt))%mo;
if(y>=mid+1)
ans=(ans+js(x,y,2*rt+1))%mo;
return ans%mo;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
int xw(int x,int y)
{
int ans=0;
while(tr[x].top!=tr[y].top)
{
if(tr[tr[x].top].dep<tr[tr[y].top].dep)
swap(x,y);
ans+=js(tr[tr[x].top].df,tr[x].df,1);
ans=ans%mo;
x=tr[tr[x].top].fa;
}
ans+=js(min(tr[x].df,tr[y].df),max(tr[x].df,tr[y].df),1);
ans=ans%mo;
return ans%mo;
}
void xg(int x,int y,int zz)
{
while(tr[x].top!=tr[y].top)
{
if(tr[tr[x].top].dep<tr[tr[y].top].dep)
swap(x,y);
xiug(tr[tr[x].top].df,tr[x].df,zz,1);
x=tr[tr[x].top].fa;
}
if(tr[tr[x].top].dep<tr[tr[y].top].dep)
swap(x,y);
xiug(tr[x].df,tr[y].df,zz,1);
}
signed main()
{
int n,m,r;
// freopen("in","rb",stdin);
// freopen("out","wb",stdout);
scanf("%lld%lld%lld%lld",&n,&m,&r,&mo);
for(int i=1;i<=n;i++)
scanf("%lld",&tr[i].val);
for(int i=1;i<n;i++)
{
int f,rr;
scanf("%lld%lld",&f,&rr);
tr[f].lj.push_back(rr);
tr[rr].lj.push_back(f);
}
dfs1(r,0,0);//求spson
dfs2(r,0);
for(int i=1;i<=n;i++)
xds[tr[i].df]=tr[i].val%mo;
build(1,n,1);
for(int ii=1;ii<=m;ii++)
{
int cz;
scanf("%lld",&cz);
if(cz==1ll)
{
int x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
xg(x,y,z);
}
if(cz==2ll)
{
int x,y;
scanf("%lld%lld",&x,&y);
printf("%lld\n",xw(x,y)%mo);
}
if(cz==3ll)
{
int x,z;
scanf("%lld%lld",&x,&z);
xiug(tr[x].df,tr[x].df+tr[x].size-1,z,1);
}
if(cz==4ll)
{
int x;
scanf("%lld",&x);
printf("%lld\n",js(tr[x].df,tr[x].df+tr[x].size-1,1)%mo);
}
}
return 0;
}//made by dshzsh
找了好久没找到错