#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0;char c=getchar();
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x;
}
int n,m,r,p;
int tot=0,nex[200005],to[200005],head[100005];
int son[100005],fa[100005],dep[100005],id[100005],size[100005],top[100005],cnt=0;
int res=0;
int w[100005],wt[100005];
inline void add(int u,int v)
{
nex[++tot]=head[u];
head[u]=tot;
to[tot]=v;
}
struct node
{
int l,r;
int ww,f;
}tree[400005];
inline void build(int l,int r,int k)
{
tree[k].l=l;tree[k].r=r;
if(l==r)
{
tree[k].ww=wt[l];tree[k].ww%=p; //
return;
}
int mid=l+r>>1;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
tree[k].ww=(tree[k*2].ww+tree[k*2+1].ww)%p;
}
inline void down(int k)
{
tree[k*2].f+=tree[k].f;
tree[k*2+1].f+=tree[k].f;
tree[k*2].ww+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
tree[k*2+1].ww+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
tree[k*2].ww%=p;
tree[k*2+1].ww%=p;
tree[k].f=0;
}
inline void ask(int k,int a,int b)
{
//cout<<"ans"<<a<<"he"<<b<<endl;
if(tree[k].l>=a&&tree[k].r<=b)
{
res+=tree[k].ww;res%=p;//printf("999");
return;
}
down(k);
int mid=(tree[k].l+tree[k].r)>>1;
if(a<=mid) ask(k*2,a,b);
if(b>mid) ask(k*2+1,a,b);//printf("888");
}
inline void change(int k,int a,int b,int ad)
{
if(tree[k].l>=a&&tree[k].r<=b)
{
tree[k].f+=ad;
tree[k].ww+=(tree[k].r-tree[k].l+1)*ad;
return;
}
if(tree[k].f) down(k);
int mid=(tree[k].l+tree[k].r)>>1;
if(a<=mid) change(k*2,a,b,ad);
if(b>mid) change(k*2+1,a,b,ad);
tree[k].ww=(tree[k*2].ww+tree[k*2+1].ww)%p;
}
//**********************************以上线段树
inline int ask2(int u,int v)
{
int ans=0;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
res=0;
ask(1,id[top[u]],id[u]);
ans+=res;
ans%=p;
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
res=0;
ask(1,id[u],id[v]);
ans+=res;
return ans%p;
}
inline void change2(int u,int v,int z)
{
z%=p;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]]) swap(u,v);
change(1,id[top[u]],id[u],z);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
change(1,id[u],id[v],z);
}
inline int askk(int k)
{
int res=0;
ask(1,id[k],id[k]+size[k]-1);
return res;
}
inline void changek(int k,int ad)
{
change(1,id[k],id[k]+size[k]-1,ad);
}
inline void dfs1(int u,int f)
{
fa[u]=f;dep[u]=dep[f]+1;
size[u]=1;int maxson=-1;
for(int i=head[u];i;i=nex[i])
{
int v=to[i];
if(v==f) continue;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>maxson)
{
maxson=size[v];
son[u]=v;
}
}
}
inline void dfs2(int u,int tp)
{
id[u]=++cnt;
wt[++cnt]=w[u];
top[u]=tp;
if(!son[u]) return;
dfs2(son[u],tp);
for(int i=head[u];i;i=nex[i])
{
int v=to[i];
if(v==son[u]||v==fa[u]) continue;
dfs2(v,v);
}
}
int main()
{
n=read();m=read();r=read();p=read();
for(int i=1;i<=n;i++)
{
w[i]=read();
}
int a,b;
for(int i=1;i<n;i++)
{
a=read();b=read();
add(a,b);add(b,a);
}
dfs1(r,0);
dfs2(r,r);
build(1,n,1);
int opt,x,y,z;
while(m--)
{
opt=read();
if(opt==1)
{
x=read();y=read();z=read();
change2(x,y,z);
}
if(opt==2)
{
x=read();y=read();
printf("%d\n",ask2(x,y));
}
if(opt==3)
{
x=read();z=read();
changek(x,z);
}
if(opt==4)
{
x=read();
printf("%d\n",askk(x));
}
}
return 0;
}