#include<bits/stdc++.h>
#define zxklovefxl 0
using namespace std;
const int Maxn=2e7+10;
int tot,cnt,head[Maxn],to[Maxn],w[Maxn],wt[Maxn],nxt[Maxn];
int a[Maxn*4],laz[Maxn*4];
int son[Maxn],id[Maxn],fa[Maxn],dep[Maxn],siz[Maxn],top[Maxn];
int n,m,r,mod,res;
void add(int u,int v)
{
tot++;
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
int ride()
{
int s=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch==-1) f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
s=s*10+ch-'0';
ch=getchar();
}
return s*f;
}
void pushdown(int rt,int lenth)
{
laz[rt*2]+=laz[rt];
laz[rt*2+1]+=laz[rt];
a[rt*2]+=laz[rt]*(lenth-(lenth/2));
a[rt*2+1]+=laz[rt]*(lenth/2);
a[rt*2]%=mod;
a[rt*2+1]%=mod;
laz[rt]=0;
}
void build(int rt,int l,int r)
{
if(l==r)
{
a[rt]=wt[l]%mod;
return ;
}
int mid=(l+r)>>1;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
a[rt]=(a[rt*2]+a[rt*2+1])%mod;
}
void query(int rt,int l,int r,int L,int R)
{
int len=(r-l)+1;
if(L<=l&&r<=R)
{
res+=a[rt]%mod;
return ;
}
else
{
if(laz[rt]) pushdown(rt,len);
int mid=(l+r)>>1;
if(L<=mid) query(rt*2,l,mid,L,R);
if(R>mid) query(rt*2+1,mid+1,r,L,R);
}
}
void updata(int rt,int l,int r,int L,int R,int k)
{
int len=r-l+1;
if(L<=l&&R<=r)
{
laz[rt]+=k;
a[rt]+=k*len;
}
else
{
int mid=(l+r)>>1;
if(laz[rt]) pushdown(rt,len);
if(L<=mid) updata(rt*2,l,mid,L,R,k);
if(R>mid) updata(rt*2+1,mid+1,r,L,R,k);
a[rt]=(a[rt*2]+a[rt*2+1])%mod;
}
}
void dfs1(int x,int f,int deep)
{
dep[x]=deep;
fa[x]=f;
siz[x]=1;
int maxson=-1;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==f) continue;
dfs1(y,x,deep+1);
siz[x]+=siz[y];
if(siz[y]>maxson) son[x]=y,maxson=siz[y];
}
}
void dfs2(int x,int topf)
{
id[x]=++cnt;
wt[cnt]=w[x];
top[x]=topf;
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
}
void updchange(int x,int y,int k)
{
k%=mod;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
updata(1,1,n,id[top[x]],id[x],k);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
updata(1,1,n,id[x],id[y],k);
}
int qrange(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
res=0;
query(1,1,n,id[top[x]],id[x]);
ans+=res%mod;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
res=0;
query(1,1,n,id[x],id[y]);
ans+=res%mod;
return ans%mod;
}
void updson(int x,int k)
{
updata(1,1,n,id[x],id[x]+siz[x]-1,k);
}
int qson(int x)
{
res=0;
query(1,1,n,id[x],id[x]+siz[x]-1);
return res%mod;
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
n=ride();
m=ride();
r=ride();
mod=ride();
for(int i=1;i<=n;i++)
{
w[i]=ride();
}
int u,v;
for(int i=1;i<n;i++)
{
u=ride();
v=ride();
add(u,v);
add(v,u);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
while(m--)
{
int k,x,y,z;
k=ride();
if(k==1)
{
x=ride();
y=ride();
z=ride();
updchange(x,y,z);
}
if(k==2)
{
x=ride();
y=ride();
cout<<qrange(x,y)<<endl;
}
if(k==3)
{
x=ride();
y=ride();
updson(x,y);
}
if(k==4)
{
x=ride();
cout<<qson(x)<<endl;
}
}
fclose(stdin);
fclose(stdout);
return 0;
}