RT

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
inline int R() {
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - 48;
ch = getchar();
}
return x * f;
}
inline void write(int x) {
if (x < 0) {
x = -x;
putchar('-');
}
int y = 0;
char z[40];
while (x || !y) {
z[y++] = x % 10 + 48;
x /= 10;
}
while (y--)
putchar(z[y]);
putchar(10);
}
const int N = 1e5 + 5;
struct edge {
int to, nxt;
} a[N << 1];
int head[N << 1], cnt;
int n, m, s, mod, w[N];
void add(int x, int y) {
cnt++;
a[cnt].to = y;
a[cnt].nxt = head[x];
head[x] = cnt;
}
int d[N << 2], b[N << 2];
int leftson(int x) {
return x >> 1;
}
int rightson(int x) {
return x >> 1 | 1;
}
void pushdown(int l, int r, int mid, int p) {
d[leftson(p)] += (mid - l + 1) * b[p], d[rightson(p)] += (r - mid) * b[p];
d[leftson(p)] %= mod, d[rightson(p)] %= mod;
b[leftson(p)] += b[p], b[rightson(p)] += b[p];
b[leftson(p)] %= mod, b[rightson(p)] %= mod;
b[p] = 0;
}
void build(int l, int r, int p) {
if (l == r) {
d[p] = w[l] % mod;
return;
}
int mid = (l + r) >> 1;
build(l, mid, leftson(p));
build(mid + 1, r, rightson(p));
d[p] = (d[leftson(p)] + d[rightson(p)]) % mod;
}
void change(int L, int R, int l, int r, int p, int k) {
if (L <= l && r <= R) {
b[p] = (b[p] + k) % mod;
d[p] = (d[p] + (r - l + 1) * k) % mod;
return;
}
int mid = (l + r) >> 1;
if (b[p])
pushdown(l, r, mid, p);
if (L <= mid)
change(L, R, l, mid, leftson(p), k);
if (R > mid)
change(L, R, mid + 1, r, rightson(p), k);
d[p] = (d[leftson(p)] + d[rightson(p)]) % mod;
}
int getsum(int L, int R, int l, int r, int p) {
if (L <= l && r <= R)
return d[p] % mod;
int mid = (l + r) >> 1, res = 0;
if (b[p])
pushdown(l, r, mid, p);
if (L <= mid)
res = (res + getsum(L, R, l, mid, leftson(p))) % mod;
if (R > mid)
res = (res + getsum(L, R, mid + 1, r, rightson(p))) % mod;
return res;
}
int dep[N], fa[N], son[N], siz[N];
void dfs1(int x, int y) {
dep[x] = dep[y] + 1;
fa[x] = y;
siz[x] = 1;
int tmp = 0;
for (int i = head[x]; i; i = a[i].nxt) {
int u = a[i].to;
if (u == y)
continue;
dfs1(u, x);
siz[x] += siz[u];
if (siz[u] > tmp) {
tmp = siz[u];
son[x] = u;
}
}
}
int top[N], dfn[N], rk[N], val[N];
void dfs2(int x, int root) {
dfn[x] = ++cnt;
val[x] = w[x];
top[x] = root;
rk[dfn[x]] = x; //oi-wiki上有记载,但在luogu上就没了?
if (!son[x])
return;
dfs2(son[x], root);
for (int i = head[x]; i; i = a[i].nxt) {
int u = a[i].to;
if (u == fa[x] || u == son[x])
continue;
dfs2(u, u);
}
}
void update(int l, int r, int k) {
while (top[l] != top[r]) {
if (dep[top[l]] < dep[top[r]])
swap(l, r);
change(dfn[top[l]], dfn[l], 1, n, 1, k);
l = fa[top[l]];
}
if (dep[l] > dep[r])
swap(l, r);
change(dfn[l], dfn[r], 1, n, 1, k);
}
int query(int l, int r) {
int res = 0;
while (top[l] != top[r]) {
if (dep[top[l]] < dep[top[r]])
swap(l, r);
res = (res + getsum(dfn[top[l]], dfn[l], 1, n, 1)) % mod;
l = fa[top[l]];
}
if (dep[l] > dep[r])
swap(l, r);
res = (res + getsum(dfn[l], dfn[r], 1, n, 1)) % mod;
return res;
}
int main() {
n = R(), m = R(), s = R(), mod = R();
for (int i = 1; i <= n; i++)
w[i] = R();
for (int i = 1, x, y; i < n; i++) {
x = R(), y = R();
add(x, y), add(y, x);
}
cnt = 0;
dfs1(s, 0);
dfs2(s, s);
build(1, n, 1);
for (int i = 1, op, l, r, v, k; i <= m; i++) {
op = R();
if (op == 1) {
l = R(), r = R(), k = R();
k %= mod;
update(l, r, k);
} else if (op == 2) {
l = R(), r = R();
write(query(l, r));
} else if (op == 3) {
v = R(), k = R();
k %= mod;
change(dfn[v], dfn[v] + siz[v] - 1, 1, n, 1, k);
} else {
v = R();
write(getsum(dfn[v], dfn[v] + siz[v] - 1, 1, n, 1));
}
}
}