const int maxn=3e5+6;
struct tree{int l,r,v,lazy;}node[maxn<<1];
struct edge{int to,next;}e[maxn<<2];
int last[maxn],w[maxn],ex[maxn],top[maxn],rank[maxn],size[maxn],dep[maxn],tt[maxn],fa[maxn],cnt;
int mod,n,m,s,tid[maxn],tot;
void insert(int u,int v){e[++cnt]=(edge){v,last[u]};last[u]=cnt;tt[u]++;}
void pushdown(int x){
if(node[x].lazy==0)return;
node[x].v+=node[x].lazy*(node[x].r-node[x].l+1)%mod;
node[lson].lazy+=node[x].lazy;node[rson].lazy+=node[x].lazy;
node[x].lazy=0;
}
void build(int x,int l,int r){
int mid=(l+r)>>1;node[x].l=l,node[x].r=r;
if(l==r)return;
build(lson,l,mid);
build(rson,mid+1,r);
}
void modify(int x,int l,int r,int val){
if(node[x].l>r||node[x].r<l)return;
if(node[x].l>=l&&node[x].r<=r){node[x].lazy+=val;pushdown(x);return;}
modify(lson,l,r,val);
modify(rson,l,r,val);
pushdown(lson);pushdown(rson);
node[x].v=(node[lson].v+node[rson].v)%mod;
}
inline int query(int x,int l,int r){
if(node[x].l>r||node[x].r<l)return 0;
if(node[x].l>=l&&node[x].r<=r)return (node[x].v)%mod;
pushdown(lson);pushdown(rson);
return (query(lson,l,r)+query(rson,l,r))%mod;
}
void dfs(int x,int Fa){
size[x]=1;dep[x]=dep[Fa]+1;fa[x]=Fa;
reg(x){
if(e[i].to==Fa)continue;
dfs(e[i].to,x);
size[x]+=size[e[i].to];
}
}
void dfs2(int x,int head){
int mson=0;
top[x]=head;tid[x]=++tot;rank[tid[x]]=tot;
modify(1,tot,tot,w[x]);
if(tt[x]==1&&x!=s){ex[x]=x;return;}
reg(x)
if(size[e[i].to]<size[x]&&size[e[i].to]>size[mson])mson=e[i].to;
dfs2(mson,head);
ex[x]=ex[mson];
reg(x)
if(size[e[i].to]<size[x]&&e[i].to!=mson){dfs2(e[i].to,e[i].to);ex[x]=ex[e[i].to];}
}
void pmodify(int x,int y,int val){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
modify(1,tid[top[x]],tid[x],val);
x=fa[top[x]];
}
if(tid[x]>tid[y])swap(x,y);
modify(1,tid[x],tid[y],val);
}
inline int pquery(int x,int y){
int re=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
re=(re+query(1,tid[top[x]],tid[x]))%mod;
x=fa[top[x]];
}
if(tid[x]>tid[y])swap(x,y);
re=(re+query(1,tid[x],tid[y]))%mod;
return re;
}
int main()
{
n=read(),m=read(),s=read(),mod=read();
rep(i,1,n)w[i]=read();
rep(i,1,n-1){
int u=read(),v=read();
insert(u,v);insert(v,u);
}
build(1,1,n);
dfs(s,0);dfs2(s,s);
rep(i,1,m){
int opt=read();
if(opt==1){int x=read(),y=read(),z=read();pmodify(x,y,z);}
if(opt==2){int x=read(),y=read();printf("%d\n",pquery(x,y)%mod);}
if(opt==3){int x=read(),y=read();modify(1,tid[x],tid[ex[x]],y);}
if(opt==4){int x=read();printf("%d\n",query(1,tid[x],tid[ex[x]])%mod);}
}
return 0;
}