#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 1e5 + 10;
int ls(int now) {
return now << 1;
}
int rs(int now) {
return now << 1 | 1;
}
int n,m,ro,p,a[N],w[N],tag[N * 4],t[N * 4];
int son[N],top[N],siz[N],f[N],dep[N],cnt,dfn[N];
int l[N * 4],r[N * 4];
vector <int> G[N];
void dfs1(int now,int fa) {
dep[now] = dep[fa] + 1;
f[now] = fa;
siz[now] = 1;
dfn[now] = ++ cnt;
for(int i=0 ; i<G[now].size() ; i++) {
int y = G[now][i];
if(y == fa) continue;
dfs1(y,now);
siz[now] += siz[y];
if(siz[y] > siz[son[now]]) son[now] = y;
}
}
void dfs2(int now,int tp) {
if(son[now]) dfs2(son[now],tp);
top[now] = tp;
for(int i=0 ; i<G[now].size() ; i++) {
int y = G[now][i];
if(y == f[now] || y == son[now]) continue;
dfs2(y,y);
}
}
void pushup(int now) {
t[now] = (t[ls(now)] + t[rs(now)]) % p;
}
void pushdown(int now) {
if(l[now] == r[now]) return ;
tag[ls(now)] += tag[now] % p;
tag[rs(now)] += tag[now] % p;
t[ls(now)] = (t[ls(now)] + 1ll * tag[now] % p * (r[ls(now)] - l[ls(now)] + 1) % p + p) % p;
t[rs(now)] = (t[rs(now)] + 1ll * tag[now] % p * (r[rs(now)] - l[rs(now)] + 1) % p+ p) % p;
tag[now] = 0;
}
void build(int now,int left,int right) {
tag[now] = 0,l[now] = left,r[now] = right;
if(left == right) {
t[now] = w[left] % p;
return ;
}
int mid = (left + right) / 2;
build(ls(now),left,mid);
build(rs(now),mid + 1,right);
pushup(now);
}
void add(int now,int left,int right,int val) {
if(l[now] == r[now]) {
t[now] = (t[now] % p + val % p + p) % p;
return ;
}
if(tag[now]) pushdown(now);
if(left <= l[now] && right >= r[now]) {
t[now] = (t[now] + 1ll * val * (r[now] - l[now] + 1) % p + p) % p;
tag[now] += val % p;
return ;
}
if(left <= r[ls(now)]) add(ls(now),left,right,val);
if(right >= l[rs(now)]) add(rs(now),left,right,val);
pushup(now);
}
int ask(int now,int left,int right) {
if(l[now] == r[now]) return t[now] % p;
if(tag[now]) pushdown(now);
if(left <= l[now] && right >= r[now]) return t[now] % p;
long long ans = 0;
if(left <= r[ls(now)]) ans = (ans + 1ll * ask(ls(now),left,right) % p + p) % p;
if(right >= l[rs(now)]) ans = (ans + 1ll * ask(rs(now),left,right) % p+ p) % p;
return (int)ans % p;
}
void add_son(int x,int val) {
add(1,dfn[x],dfn[x] + siz[x] - 1,val);
}
int ask_son(int x) {
return ask(1,dfn[x],dfn[x] + siz[x] - 1) % p;
}
void add_range(int x,int y,int val) {
val %= p;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x,y);
add(1,dfn[top[x]],dfn[x],val);
x = f[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
add(1,dfn[x],dfn[y],val);
}
int ask_range(int x,int y) {
int ans = 0;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x,y);
ans = (ans + ask(1,dfn[top[x]],dfn[x]) + p) % p;
x = f[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
ans = (ans + ask(1,dfn[x],dfn[y]) + p) % p;
return ans % p;
}
int main() {
scanf("%d%d%d%d",&n,&m,&ro,&p);
for(int i=1 ; i<=n ; i++) scanf("%d",&a[i]);
for(int i=1 ; i<n ; i++) {
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs1(ro,0);
dfs2(ro,ro);
for(int i=1 ; i<=n ; i++) w[dfn[i]] = a[i] % p;
build(1,1,n);
for(int i=1 ; i<=m ; i++) {
int opt,x,y,z;
scanf("%d",&opt);
if(opt == 1) {
scanf("%d%d%d",&x,&y,&z);
z %= p;
add_range(x,y,z);
}
else if(opt == 2) {
scanf("%d%d",&x,&y);
printf("%d\n",ask_range(x,y));
}
else if(opt == 3) {
scanf("%d%d",&x,&z);
z %= p;
add_son(x,z);
}
else {
scanf("%d",&x);
printf("%d\n",ask_son(x));
}
}
return 0;
}