using namespace std;
const long long maxn=2000005;
long long n,m,r,ts,tt,mod,a[maxn],du[maxn],c[maxn],lt[maxn],de[maxn],fath[maxn],f[maxn],d[maxn],dd[maxn],p[maxn],pp[maxn],fso[maxn];
vector<long long>v[maxn];
struct uu
{
long long l,r,s;
}te[maxn*4];
void read(long long &s)
{
s=0;
long long f=1;
char c=getchar();
while(!isdigit(c))
{
if(c=='-')f=-1;
c=getchar();
}
while(isdigit(c))
{
s=(s<<3)+(s<<1)+(c-48);
c=getchar();
}
s=s*f;
}
void dfs1(long long x,long long fa)
{
d[x]=++ts;
de[x]=de[fa]+1;
fath[x]=fa;
long long mm=0;
for(auto y:v[x])
{
if(y==fa)continue;
dfs1(y,x);
p[x]+=p[y];
if(p[y]>mm)
{
mm=p[y];
fso[x]=y;
}
}
p[x]++;
}
void dfs2(long long x,long long fa)
{
d[x]=++ts;
dd[x]=d[x];
du[ts]=x;
f[fso[x]]=f[x];
c[fso[x]]=c[x];
pp[f[x]]=max(pp[f[x]],d[fso[x]]);
if(fso[x])dfs2(fso[x],x);
dd[x]=max(dd[x],dd[fso[x]]);
for(auto y:v[x])
{
if(y==fa||y==fso[x])continue;
f[y]=y;
c[y]=++tt;
pp[y]=d[y];
dfs2(y,x);
dd[x]=max(dd[x],dd[y]);
}
}
void build(long long l,long long r,long long x)
{
te[x].l=l;
te[x].r=r;
if(l==r)
{
te[x].s=a[du[l]];
return;
}
else
{
build(l,(l+r)/2,x*2);
build((l+r)/2+1,r,x*2+1);
te[x].s=(te[x*2].s+te[x*2+1].s)%mod;
}
}
void change(long long x,long long l,long long r,long long o)
{
if(l==te[x].l&&r==te[x].r)
{
lt[x*2]+=o;
lt[x*2]%=mod;
lt[x*2+1]+=o;
lt[x*2+1]%=mod;
te[x].s+=(r-l+1)*o;
te[x].s%=mod;
}
else
{
if(r<=te[x*2].r)change(x*2,l,r,o);
else if(l>=te[x*2+1].l)change(x*2+1,l,r,o);
else
{
change(x*2,l,te[x*2].r,o);
change(x*2+1,te[x*2+1].l,r,o);
}
te[x].s=(te[x*2].s+te[x*2+1].s)%mod;
}
}
void ss1(long long x,long long y,long long z)
{
if(c[x]==c[y])change(1,min(d[x],d[y]),max(d[x],d[y]),z);
else if(de[f[x]]>de[f[y]])
{
change(1,d[f[x]],d[x],z);
x=fath[f[x]];
ss1(x,y,z);
}
else
{
change(1,d[f[y]],d[y],z);
y=fath[f[y]];
ss1(x,y,z);
}
}
long long find(long long x,long long l,long long r)
{
if(lt[x])
{
lt[x*2]=(lt[x*2]+lt[x])%mod;
lt[x*2+1]=(lt[x*2+1]+lt[x])%mod;
te[x*2].s=(te[x*2].s+lt[x*2]*(te[x*2].r-te[x*2].l+1))%mod;
te[x*2+1].s=(te[x*2+1].s+lt[x*2+1]*(te[x*2+1].r-te[x*2+1].l+1))%mod;
lt[x]=0;
}
if(te[x].l==l&&te[x].r==r)return te[x].s;
else
{
if(r<=te[x*2].r)return find(x*2,l,r);
else if(l>=te[x*2+1].l)return find(x*2+1,l,r);
else return (find(x*2,l,te[x*2].r)+find(x*2+1,te[x*2+1].l,r))%mod;
}
}
long long ss2(long long x,long long y)
{
long long ans=0;
if(c[x]==c[y])ans=(ans+find(1,min(d[x],d[y]),max(d[x],d[y])))%mod;
else if(de[f[x]]>de[f[y]])
{
ans=(ans+find(1,d[f[x]],d[x]))%mod;
x=fath[f[x]];
ans=(ans+ss2(x,y))%mod;
}
else
{
ans=(ans+find(1,d[f[y]],d[y]))%mod;
y=fath[f[y]];
ans=(ans+ss2(x,y))%mod;
}
return ans;
}
int main()
{
read(n);read(m);read(r);read(mod);
for(long long i=1;i<=n;i++)read(a[i]);
for(long long i=1;i<n;i++)
{
long long x,y;
read(x);
read(y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs1(r,0);
c[r]=++tt;
ts=0;
dfs2(r,0);
build(1,n,1);
for(long long i=1;i<=m;i++)
{
long long opt,x,y,z;
read(opt);
if(opt==1)
{
read(x);read(y);read(z);
ss1(x,y,z);
}
else if(opt==2)
{
read(x);read(y);
printf("%lld\n",ss2(x,y)%mod);
}
else if(opt==3)
{
read(x);read(y);
change(1,d[x],dd[x],y);
}
else
{
read(x);
printf("%lld\n",find(1,d[x],dd[x])%mod);
}
}
return 0;
}