#include <bits/stdc++.h>
#define awa cerr << "xlx is my superman!!!!!!!!!!!\n";
#define FOR(x,l,r) for(int (x) = (l); (x) <= (r); (x)++)
#define _FOR(x,l,r) for(int (x) = (r); (x) >= (l); (x)--)
#define gc getchar()
#define pb emplace_back
#define mp make_pair
#define pii pair<int, int >
#define PII pair<ll, ll >
#define fi first
#define se second
#define p_q priority_queue
#define il inline
using namespace std;
typedef long long ll;
const int N = 1e5 + 5,MOD = 1e9 + 7;
namespace cxz_0
{
il int read(int x=0,bool f=0,char c=gc){while(!isdigit(c))f=c=='-',c=gc;while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=gc;return f?-x:x;}
il void write(int x){if(x<0)x=-x,putchar('-');if(x>9)write(x/10);putchar(x%10+'0');}
il ll readl(ll x=0,bool f=0,char c=gc){while(!isdigit(c))f=c=='-',c=gc;while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=gc;return f?-x:x;}
il void writel(ll x){if(x<0)x=-x,putchar('-');if(x>9)write(x/10);putchar(x%10+'0');}
il int qpow(int a, int n, int p){int b=1;while(n){if(n&1)b=1ll*b*a%p;a=1ll*a*a%p;n>>=1;}return b;}
il int max(int&a,int&b){return a>b?a:b;}
il int min(int&a,int&b){return a<b?a:b;}
il void swap(int&a,int&b){a^=b^=a^=b;}
il int Mod(int x){return x>MOD?Mod(x-MOD):x;}
} using namespace cxz_0;
struct Node
{
int nxt, to;
}e[N << 1];
struct Segtr
{
int sum, add;
#define lc (p << 1)
#define rc (p << 1 | 1)
#define MID int mid = (l + r) >> 1
}tr[N << 2];
int n, m, r, mod, a[N], cnt, tot, head[N], f[N], d[N], siz[N], son[N], rk[N], top[N], id[N];
il void add_edge (int u, int v)
{
e[++tot].to = v;
e[tot].nxt = head[u];
head[u] = tot;
}
il void pushup (int p)
{
tr[p].sum = (tr[lc].sum + tr[rc].sum) % mod;
}
il void pushdown (int p, int l, int r)
{
if (tr[p].add)
{
MID;
(tr[lc].sum += tr[p].add * (mid - l + 1)) %= mod;
(tr[rc].sum += tr[p].add * (r - mid)) %= mod;
tr[lc].add += tr[p].add;
tr[rc].add += tr[p].add;
tr[p].add = 0;
}
}
il void build (int p, int l, int r)
{
if (l == r)
{
tr[p].sum = rk[l] % mod;
return;
}
MID;
build (lc, l, mid);
build (rc, mid + 1, r);
pushup (p);
}
il void modify (int p, int l, int r, int ql, int qr, int k)
{
if (ql <= l && r <= qr)
{
(tr[p].add += k) %= mod;
(tr[p].sum += k * (r - l + 1)) %= mod;
return;
}
MID;
if (mid >= ql) modify(lc, l, mid, ql, qr, k);
if (mid < qr) modify(rc, mid + 1, r, ql, qr, k);
pushup (p);
}
il int query (int p, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr) return tr[p].sum;
pushdown (p, l, r);
MID;
int ret = 0;
if (mid >= ql) ret += query(lc, l, mid, ql, qr);
if (mid < qr) ret += query(rc, mid + 1, r, ql, qr);
return ret;
}
il void dfs1 (int u, int fa)
{
f[u] = fa;
d[u] = d[fa] + 1;
siz[u] = 1;
int maxson = 0;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa) continue;
dfs1 (v, u);
siz[u] += siz[v];
if (siz[v] > maxson) son[u] = v, maxson = siz[v];
}
}
il void dfs2 (int u, int t)
{
top[u] = t;
id[u] = ++cnt;
rk[cnt] = a[u];
if (!son[u]) return;
dfs2 (son[u], t);
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v != son[u] && v != f[u]) dfs2 (v, v);
}
}
il int sum (int x, int y)
{
int ret = 0;
while (top[x] != top[y])
{
if (d[top[x]] < d[top[y]]) swap(x, y);
(ret += query(1, 1, n, id[top[x]], id[x])) %= mod;
x = f[top[x]];
}
if (id[x] > id[y]) swap(x, y);
return (ret + query (1, 1, n, id[x], id[y])) % mod;
}
il void update (int x, int y, int c)
{
while (top[x] != top[y])
{
if (d[top[x]] < d[top[y]]) swap(x, y);
modify (1, 1, n, id[top[x]], id[x], c);
x = f[top[x]];
}
if (id[x] > id[y]) swap(x, y);
modify (1, 1, n, id[x], id[y], c);
}
signed main()
{
#ifndef ONLINE_JUDGE
double start = clock();
freopen("P3384_2.in", "r", stdin);
freopen("P3384.out", "w", stdout);
#endif
n = read(), m = read(), r = read(), mod = read();
FOR (i, 1, n) a[i] = read();
FOR (i, 1, n - 1)
{
int u = read(), v = read();
add_edge(u, v);
add_edge(v, u);
}
dfs1 (r, 0);
dfs2 (r, r);
build (1, 1, n);
cerr << endl;
while (m--)
{
int op = read(), x = read(), y, z;
if (op == 1)
{
y = read(), z = read();
update (x, y, z);
}
else if (op == 2)
{
y = read();
cout << sum (x, y) << "\n";
}
else if (op == 3)
{
y = read();
modify (1, 1, n, id[x], id[x] + id[siz[x]] - 1, y);
}
else cout << query (1, 1, n, id[x], id[siz[x]] - 1) << "\n";
}
#ifndef ONLINE_JUDGE
cerr << "Time: " << 1e3 * (clock() - start) / CLOCKS_PER_SEC << " ms" << endl;
awa
#endif
return 0;
}