#include<bits/stdc++.h>
int n,m,r,p;
std::vector<int> g[100005];
int w[100005];
void input(void){
int x,y;
scanf("%d%d%d%d",&n,&m,&r,&p);
for(int i = 1;i <= n;++ i)
scanf("%d",w+i);
for(int i = 1;i <= n-1;++ i){
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
return;
}
int siz[100005],dep[100005],fa[100005],son[100005];
void dfs1(int id,int f){
dep[id] = dep[f] + 1;
fa[id] = f;
siz[id] = 1;
for(auto v : g[id]){
if(v == f)
continue;
dfs1(v,id);
siz[id] += siz[v];
son[id] = siz[v]>siz[son[id]] ? v : son[id];
}
return;
}
int a[100005],dfn[100005],top[100005],tot = 1;
void dfs2(int id,int t){
a[tot] = w[id];
dfn[id] = tot;
++ tot;
top[id] = t;
if(!son[id])
return;
dfs2(son[id],t);
for(auto v : g[id]){
if(dfn[v])
continue;
dfs2(v,v);
}
return;
}
int d[100005*4],t[100005*4];
#define mid ((l+r)>>1)
#define lc (id<<1)
#define rc (id<<1|1)
void build(int id,int l,int r){
if(l == r)
d[id] = a[l];
else{
build(lc,l,mid);
build(rc,mid+1,r);
d[id] = (d[lc] + d[rc]) % p;
}
return;
}
void pushdown(int id,int l,int r){
d[lc] = (d[lc] + (mid - l + 1) * t[id] % p) % p;
d[rc] = (d[rc] + (r - mid) * t[id] % p) % p;
t[lc] = (t[lc] + t[id]) % p;
t[rc] = (t[rc] + t[id]) % p;
t[id] = 0;
return;
}
void modify(int id,int l,int r,int s,int e,int c){
if(l == r)
d[id] += c;
else{
if(s <= l && e >= r){
d[id] = (d[id] + c * (r - l + 1) % p) % p;
t[id] = (t[id] + c) % p;
}else{
pushdown(id,l,r);
if(s <= mid)
modify(lc,l,mid,s,e,c);
if(e > mid)
modify(rc,mid+1,r,s,e,c);
d[id] = (d[lc] + d[rc]) % p;
}
}
return;
}
int query(int id,int l,int r,int s,int e){
if(l == r)
return d[id];
if(s <= l && e >= r)
return d[id];
pushdown(id,l,r);
int ans = 0;
if(s <= mid)
ans = (ans + query(lc,l,mid,s,e)) % p;
if(e > mid)
ans = (ans + query(rc,mid+1,r,s,e)) % p;
return ans;
}
#undef mid
#undef lc
#undef rc
using std::swap;
void modify1(int x,int y,int z){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])
swap(x,y);
modify(1,1,n,dfn[top[x]],dfn[x],z);
x = fa[top[x]];
}
if(dep[x] < dep[y])
swap(x,y);
modify(1,1,n,dfn[y],dfn[x],z);
return;
}
int query1(int x,int y){
int ans = 0;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]])
swap(x,y);
ans = (ans + query(1,1,n,dfn[top[x]],dfn[x])) % p;
x = fa[top[x]];
}
if(dep[x] < dep[y])
swap(x,y);
ans = (ans + query(1,1,n,dfn[y],dfn[x])) % p;
return ans;
}
void modify2(int x,int z){
modify(1,1,n,dfn[x],dfn[x]+siz[x]-1,z);
return;
}
int query2(int x){
return query(1,1,n,dfn[x],dfn[x+siz[x]-1]);
}
int main(void){
int op,x,y,z;
input();
dfs1(r,0);
dfs2(r,r);
build(1,1,n);
while(m --){
scanf("%d%d",&op,&x);
switch(op){
case 1:
scanf("%d%d",&y,&z);
modify1(x,y,z%p);
break;
case 2:
scanf("%d",&y);
printf("%d\n",query1(x,y));
break;
case 3:
scanf("%d",&z);
modify2(x,z%p);
break;
case 4:
printf("%d\n",query2(x));
}
}
return 0;
}