RT
#include <bits/stdc++.h>
#define maxn 100005
using namespace std;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
int n, m, r, mod;
struct edge{
int v, nxt;
}e[maxn];
int head[maxn], cnt, tot;
void add(int u, int v) {
e[++cnt] = { v, head[u] };
head[u] = cnt;
}
struct node{
int l, r, sum, tag;
}t[maxn << 1];
int w[maxn], dep[maxn], f[maxn], son[maxn], siz[maxn];
int id[maxn], w2[maxn], top[maxn];
void dfs1(int x, int fa) {
dep[x] = dep[fa] + 1, f[x] = fa, siz[x] = 1;
int maxson = -1;
for (int i = head[x]; i; i = e[i].nxt) {
int y = e[i].v;
if (y == fa) continue;
dfs1(y, x);
siz[x] += siz[y];
if (siz[y] > maxson) son[x] = y, maxson = siz[y];
}
}
void dfs2(int x, int topf) {
id[x] = ++tot;
w2[tot] = w[x], top[x] = topf;
if (!son[x]) return;
dfs2(son[x], topf);
for (int i = head[x]; i; i = e[i].nxt) {
int y = e[i].v;
if (y == f[x] || y == son[x]) continue;
dfs2(y, y);
}
}
void build(int p, int l, int r) {
t[p].l = l, t[p].r = r;
if (l == r) {
t[p].sum = w2[l];
return;
}
int mid = l + r >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
t[p].sum = t[p << 1].sum + t[p << 1 | 1].sum;
}
void pushdown(int p) {
if (!t[p].tag) return;
t[p << 1].tag += t[p].tag;
t[p << 1].tag %= mod;
t[p << 1].sum += (t[p << 1].r - t[p << 1].l + 1) * t[p << 1].tag;
t[p << 1].sum %= mod;
t[p << 1 | 1].tag += t[p].tag;
t[p << 1 | 1].tag %= mod;
t[p << 1 | 1].sum += (t[p << 1 | 1].r - t[p << 1 | 1].l + 1) * t[p << 1 | 1].tag;
t[p << 1 | 1].sum %= mod;
t[p].tag = 0;
}
void change(int p, int l, int r, int v) {
if (l <= t[p].l && t[p].r <= r) {
t[p].tag += v;
t[p].tag %= mod;
t[p].sum += (t[p].r - t[p].l + 1) * v;
t[p].sum %= mod;
return;
}
pushdown(p);
int mid = t[p].l + t[p].r >> 1;
if (l <= mid) change(p << 1, l, r, v);
if (r > mid) change(p << 1 | 1, l, r, v);
return;
}
int query(int p, int l, int r) {
if (l <= t[p].l && t[p].r <= r) return t[p].sum % mod;
pushdown(p);
int res = 0, mid = t[p].l + t[p].r >> 1;
if (l <= mid) res += query(p << 1, l, r), res %= mod;
if (mid < r) res += query(p << 1 | 1, l, r), res %= mod;
return res % mod;
}
void upd_route(int x, int y, int z) {
z %= mod;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
change(1, id[top[x]], id[x], z);
x = f[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
change(1, id[x], id[y], z);
}
int query_route(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query(1, id[top[x]], id[x]);
ans %= mod;
x = f[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans += query(1, id[x], id[y]);
return ans % mod;
}
void upd_son(int x, int z) {
change(1, id[x], id[x] + siz[x] - 1, z);
}
int query_son(int x) {
return query(1, id[x], id[x] + siz[x] - 1);
}
signed main() {
n = read(), m = read(), r = read(), mod = read();
for (int i = 1; i <= n; i++) w[i] = read();
for (int i = 1; i < n; i++) {
int u = read(), v = read();
add(u, v), add(v, u);
}
dfs1(r, 0);
dfs2(r, r);
build(1, 1, n);
while (m--) {
int opt = read();
if (opt == 1) {
int x = read(), y = read(), z = read();
upd_route(x, y, z);
}
if (opt == 2) {
int x = read(), y = read();
cout << query_route(x, y) % mod << endl;
}
if (opt == 3) {
int x = read(), z = read();
upd_son(x, z);
}
if (opt == 4) {
int x = read();
cout << query_son(x) % mod << endl;
}
}
}