#include<bits/stdc++.h>
using namespace std;
int u,v,top[500005],fa[500005],hs[500005],d[500005],siz[500005],dfn[500005],cnt;
long long n,k,r,m,x,y,z,ans,lzy1[400005],a[100005];
char op;
struct xds
{
long long v,l,r;
}t[400005];
vector<int>mp[500005];
inline void build(register long long u,register long long l,register long long r)
{
t[u].l = l;t[u].r = r;
if(l == r)
{
t[u].v = a[dfn[l]];
t[u].v%=m;
return;
}
register long long _ = l+r>>1;
build(u<<1,l,_);build((u<<1)+1,_+1,r);
t[u].v = (t[u<<1].v+t[(u<<1)+1].v)%m;
}
inline void upd(register long long u,register long long add)
{
lzy1[u] = (lzy1[u]+add)%m;
t[u].v = (t[u].v+(t[u].r-t[u].l+1)*add)%m;
}
inline void pushdown(register long long u)
{
upd(u<<1,lzy1[u]);
upd((u<<1)+1,lzy1[u]);
lzy1[u] = 0;
}
inline void update(register long long u,register long long l,register long long r,register long long add)
{
if(l>r)swap(l,r);
if(t[u].l>=l&&t[u].r<=r)
{
upd(u,add);
return;
}
if(t[u].l!=t[u].r)pushdown(u);
long long _ = t[u].l+t[u].r>>1;
if(l<=_)update(u<<1,l,r,add);
if(r>_) update((u<<1)+1,l,r,add);
t[u].v=(t[u<<1].v+t[(u<<1)+1].v)%m;
}
inline long long query(register long long u,register long long l,register long long r)
{
if(l>r)swap(l,r);
register long long v = 0;
if(t[u].l>=l&&t[u].r<=r)return t[u].v;
if(t[u].l!=t[u].r)pushdown(u);
register long long _ = t[u].l+t[u].r>>1;
if(l<=_)v+=query(u<<1,l,r);
if(r>_) v+=query((u<<1)+1,l,r);
t[u].v=(t[u<<1].v+t[(u<<1)+1].v)%m;
return v%m;
}
void dfs(int u,int f)
{
fa[u] = f;
d[u] = d[f]+1;
register int tmp = 0;
for(register int i = 0;i<mp[u].size();i++)
if(mp[u][i]!=f)
{
dfs(mp[u][i],u);
if(siz[mp[u][i]]>tmp||(siz[mp[u][i]]==tmp&&hs[u]>mp[u][i]))
{
tmp = siz[mp[u][i]];
hs[u] = mp[u][i];
}
siz[u]+=siz[mp[u][i]];
}
siz[u]++;
}
void dfs1(int u,int f)
{
dfn[u] = ++cnt;
fa[u] = f;
if(hs[f]!=u) top[u] = u;
else top[u] = top[f];
if(hs[u])dfs1(hs[u],u);
for(register int i = 0;i<mp[u].size();i++)
if(mp[u][i]!=f&&mp[u][i]!=hs[u])dfs1(mp[u][i],u);
}
void uplca(int x,int y,long long z)
{
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]])update(1,dfn[top[x]],dfn[x],z),x = fa[top[x]];
else update(1,dfn[top[y]],dfn[y],z),y = fa[top[y]];
}
if(d[x]>=d[y])update(1,dfn[y],dfn[x],z);
else if(d[y]>d[x])update(1,dfn[x],dfn[y],z);
}
int qlca(int x,int y)
{
register long long res = 0;
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]]) res+=query(1,dfn[top[x]],dfn[x]),res%=m,x = fa[top[x]];
else res+=query(1,dfn[top[y]],dfn[y]),res%=m,y = fa[top[y]];
}
if(d[x]>=d[y])res+=query(1,dfn[y],dfn[x]),res%=m;
else if(d[y]>d[x])res+=query(1,dfn[x],dfn[y]),res%=m;
return res;
}
int main()
{
cin>>n>>k>>r>>m;
for(register int i = 1;i<=n;i++)cin>>a[i];
for(register int i = 1;i<n;i++)
{
cin>>u>>v;
mp[u].push_back(v);
mp[v].push_back(u);
}
dfs(r,r);
dfs1(r,r);
build(1,1,n);
while(k--)
{
cin>>op;
if(op == '1')
{
cin>>x>>y>>z;
uplca(x,y,z);
}
else if(op == '2')
{
cin>>x>>y;
ans = qlca(x,y);
cout<<ans<<'\n';
}
else if(op == '3')
{
cin>>x>>z;
update(1,dfn[x],dfn[x]+siz[x]-1,z);
}
else
{
cin>>x;
ans = query(1,dfn[x],dfn[x]+siz[x]-1);
cout<<ans<<'\n';
}
}
}