#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
using namespace std;
inline int read()
{
int x = 0;
int k = 1;
char c = getchar();
while (!isdigit(c))
if (c == '-') k = -1, c = getchar();
else c = getchar();
while (isdigit(c))
x = (x << 3) + (x << 1) + (c ^ 48),
c = getchar();
return k * x;
}
struct edge
{
int u;
int v;
int next;
}e[200020];
int n, m, r, mod, cnt, nid = 0;
int val[1000200];
int dep[1002000];
int siz[1002000];
int faz[1002000];
int top[1002000];
int son[1000200];
int tid[1000200];
int lid[1002000];
int nv[1002000];
int f[1002000];
void addedge(int x, int y)
{
++cnt;
e[cnt].u = x;
e[cnt].v = y;
e[cnt].next = f[x];
f[x] = cnt;
}
void dfs1(int u, int father, int depth)
{
faz[u] = father;
dep[u] = depth;
siz[u] = 1;
for (int i = f[u]; i != -1; i = e[i].next)
{
int to = e[i].v;
if (to == father) continue;
dfs1(to, u, depth + 1);
siz[u] += siz[to];
if (son[u] == -1 || siz[son[u]] < siz[to]) son[u] = to;
}
}
void dfs2(int u, int h)
{
++nid;
top[u] = h;
nv[nid] = val[u];
lid[u] = nid;
if (son[u] == -1) return;
dfs2(son[u], h);
for (int i = f[u]; i != -1; i = e[i].next)
{
int to = e[i].v;
if (!lid[to])
dfs2(to, to);
}
}
//Segmenttree Begins!!!
#define ls u << 1
#define rs u << 1 | 1
struct tree
{
int l;
int r;
int w;
int siz;
int f;
}t[2000100];
void update(int u) { t[u].w = (t[ls].w + t[rs].w + mod) % mod; }
void build(int u, int l, int r)
{
t[u].l = l;
t[u].r = r;
t[u].siz = r - l + 1;
if (l == r)
{
t[u].w = nv[l];
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
update(u);
}
void pushdown(int u)
{
if (!t[u].f) return;
t[ls].w = (t[ls].w + t[ls].siz * t[u].f) % mod;
t[rs].w = (t[rs].w + t[rs].siz * t[u].f) % mod;
t[ls].f = (t[ls].f + t[u].f) % mod;
t[rs].f = (t[rs].f + t[u].f) % mod;
t[u].f = 0;
}
void add(int u, int l, int r, int x)
{
if (l <= t[u].l && r >= t[u].r)
{
t[u].w += t[u].siz * x;
t[u].f += x;
return;
}
pushdown(u);
int mid = (t[u].l + t[u].r) >> 1;
if (l <= mid) add(ls, l, r, x);
if (r > mid) add(rs, l, r, x);
update(u);
}
int sum(int u, int l, int r)
{
int ans = 0;
if (l <= t[u].l && t[u].r <= r) return t[u].w;
pushdown(u);
int mid = (t[u].l + t[u].r) >> 1;
if (l <= mid) ans = (ans + sum(ls, l, r)) % mod;
if (r > mid) ans = (ans + sum(rs, l, r)) % mod;
return ans;
}
//operator in tree sparate
void tadd(int x, int y, int c)
{
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]]) swap(x, y);
add(1, lid[top[x]], lid[x], c);
x = faz[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
add(1, lid[x], lid[y], c);
}
void tsum(int x, int y)
{
int ans = 0;
while (top[x] != top[y])
{
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans = (ans + sum(1, lid[top[x]], lid[x])) % mod;
x = faz[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans = (ans + sum(1, lid[x], lid[y])) % mod;
printf("%d\n", ans);
}
int main()
{
memset(f, -1, sizeof(f));
memset(son, -1, sizeof(son));
n = read();
m = read();
r = read();
mod = read();
for (int i = 1; i <= n; ++i) val[i] = read();
for (int i = 1; i < n; ++i)
{
int x, y;
x = read();
y = read();
addedge(x, y);
addedge(y, x);
}
dfs1(r, 0, 1);
dfs2(r, r);
build(1, 1, n);
for (int i = 1; i <= m; ++i)
{
int opr = read();
int x, y, z;
x = read();
if (opr == 1)
{
y = read();
z = read();
z = z % mod;
tadd(x, y, z);
}
else if (opr == 2)
{
y = read();
tsum(x, y);
}
else if (opr == 3)
{
z = read();
add(1, lid[x], lid[x] + siz[x] - 1, z % mod);
}
else if (opr == 4)
printf("%d\n", sum(1, lid[x], lid[x] + siz[x] - 1));
}
return 0;
}