#include <cstdio>
#include <algorithm>
#include <cstring>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int rd() {
int x = 0, w = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') w = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x * 10 + (c - '0');
c = getchar();
}
return x * w;
}
const int N = 1e5 + 5, M = 1e5 + 5;
int n, m, q;
int son[N], siz[N], fa[N], dep[N];
int dfn[N], rk[N];
int w[N], wt[N];
struct Graph {
int v, nxt;
}e[M << 1];
int lk[N], ltp;
void ins(int u, int v) {
e[++ltp] = (Graph) {v, lk[u]};
lk[u] = ltp;
}
int top[N], cnt;
int mod;
void dfs1(int u) {
son[u] = -1;
siz[u] = 1;
for(int i = lk[u]; i; i = e[i].nxt) {
int v = e[i].v;
if(!dep[v]) {
dep[v] = dep[u] + 1;
fa[v] = u;
dfs1(v);
siz[u] += siz[v];
if(son[u] == -1 || siz[v] > siz[son[u]])
son[u] = v;
}
}
}
void dfs2(int u, int t) {
top[u] = t;
++cnt;
dfn[u] = cnt;
rk[cnt] = u;
wt[cnt] = w[u];
if(son[u] == -1) return ;
dfs2(son[u], t);
for(int i = lk[u]; i; i = e[i].nxt) {
int v = e[i].v;
if(v != son[u] && v != fa[u])
dfs2(v, v);
}
}
int lca(int u, int v) {
while(top[u] != top[v]) {
if(dep[top[u]] > dep[top[v]]) u = fa[top[u]];
else v = fa[top[v]];
}
return dep[u] > dep[v] ? v : u;
}
struct Tree {
int l, r;
int dat, tag;
#define l(x) t[x].l
#define r(x) t[x].r
#define dat(x) t[x].dat
#define tag(x) t[x].tag
}t[N << 2];
void build(int p, int l, int r) {
l(p) = l, r(p) = r;
if(l == r) {
dat(p) = wt[l];
return ;
}
int mid = (r - l) / 2 + l;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
dat(p) = (dat(p << 1) + dat(p << 1 | 1)) % mod;
}
void spr(int p) {
if(tag(p)) {
tag(p << 1) += tag(p);
tag(p << 1 | 1) += tag(p);
dat(p << 1) += tag(p) * (r(p << 1) - l(p << 1) + 1);
dat(p << 1 | 1) += tag(p) * (r(p << 1 | 1) - l(p << 1 | 1) + 1);
dat(p << 1) %= mod;
dat(p << 1 | 1) %= mod;
tag(p) = 0;
}
}
void change(int p, int l, int r, int x) {
if(l <= l(p) && r(p) <= r) {
tag(p) += x;
dat(p) += (r - l + 1) * x;
dat(p) %= mod;
return ;
}
spr(p);
int mid = (r(p) - l(p)) / 2 + l(p);
if(l <= mid) change(p << 1, l, r, x);
if(r > mid) change(p << 1 | 1, l, r, x);
dat(p) = (dat(p << 1) + dat(p << 1 | 1)) % mod;
}
int ask(int p, int l, int r) {
int res = 0;
if(l <= l(p) && r(p) <= r) return dat(p);
spr(p);
int mid = (r(p) - l(p)) / 2 + l(p);
if(l <= mid) res += ask(p << 1, l, r);
if(r > mid) res += ask(p << 1 | 1, l, r);
return res;
}
int main() {
n = rd(), m = rd(), q = rd(), mod = rd();
for(int i = 1; i <= n; ++i)
w[i] = rd();
for(int i = 1; i < n; ++i) {
int u = rd(), v = rd();
ins(u, v);
ins(v, u);
}
dep[q] = 1;
dfs1(q);
dfs2(q, q);
build(1, 1, n);
while(m--) {
int opt = rd();
if(opt == 1) {
int u = rd(), v = rd(), w = rd();
w %= mod;
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
change(1, dfn[top[u]], dfn[u], w);
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u, v);
change(1, dfn[u], dfn[v], w);
} else if(opt == 2) {
int u = rd(), v = rd();
int ans = 0;
while(top[u] != top[v]) {
if(dep[top[u]] < dep[top[v]]) swap(u, v);
ans += ask(1, dfn[top[u]], dfn[u]);
ans %= mod;
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u, v);
ans += ask(1, dfn[u], dfn[v]);
printf("%d\n", ans % mod);
} else if(opt == 3) {
int u = rd(), w = rd();
change(1, dfn[u], dfn[u] + siz[u] - 1, w);
} else {
int u = rd();
printf("%d\n", ask(1, dfn[u], dfn[u] + siz[u] - 1));
}
}
return 0;
}