#include <bits/stdc++.h>
using namespace std;
int n, m, sq, r, p;
long long w[100005];
vector<int> G[100005];
int dep[100005], fa[100005], son[100005], siz[100005];
int in[100005], out[100005], times, top[100005];
long long wt[100005];
int st[1005], ed[1005], block[100005];
long long ad[1005], sum[1005], res;
void dfs1(int u, int f, int deep)
{
dep[u] = deep;
fa[u] = f;
siz[u] = 1;
int maxson = -1;
for (int i = 0 ; i < G[u].size() ; i ++)
{
int v = G[u][i];
if (v != f)
{
dfs1(v, u, deep + 1);
siz[u] += siz[v];
if (maxson < siz[v])
{
son[u] = v;
maxson = siz[v];
}
}
}
}
void dfs2(int u, int topf)
{
in[u] = ++ times;
top[u] = topf;
wt[times] = w[u];
if (!son[u])
{
return ;
}
dfs2(son[u], u);
for (int i = 0 ; i < G[u].size() ; i ++)
{
int v = G[u][i];
if (v != fa[u] && v != son[u])
{
dfs2(v, topf);
}
}
out[u] = times;
}
void add(int l, int r, int k)
{
int lb = block[l], rb = block[r];
if (lb == rb)
{
for (int i = l ; i <= r ; i ++)
{
wt[i] += k;
sum[lb] += k;
wt[i] %= p;
sum[lb] %= p;
}
return ;
}
for (int i = l ; i <= ed[lb] ; i ++)
{
wt[i] += k;
sum[lb] += k;
w[i] %= p;
sum[lb] %= p;
}
for (int i = st[rb] ; i <= r ; i ++)
{
wt[i] += k;
sum[rb] += k;
wt[i] %= p;
sum[rb] %= p;
}
for (int i = lb + 1 ; i <= rb - 1 ; i ++)
{
ad[i] += k;
ad[i] %= p;
}
}
long long query(int l, int r)
{
int lb = block[l], rb = block[r];
long long ans = 0;
if (lb == rb)
{
for (int i = l ; i <= r ; i ++)
{
ans += wt[i] + ad[lb];
ans %= p;
}
return ans;
}
for (int i = l ; i <= ed[lb] ; i ++)
{
ans += wt[i] + ad[lb];
ans %= p;
}
for (int i = st[rb] ; i <= r ; i ++)
{
ans += wt[i] + ad[rb];
ans %= p;
}
for (int i = lb + 1 ; i <= rb - 1 ; i ++)
{
ans += sum[i] % p + ad[i] * (ed[i] - st[i] + 1) % p;
}
return ans;
}
void change1(int l, int r, int k)
{
k %= p;
while (top[l] != top[r])
{
if(dep[top[l]] < dep[top[r]])
{
swap(l, r);
}
add(in[top[l]], in[l], k);
l = fa[top[l]];
}
if (dep[l] > dep[r])
{
swap(l, r);
}
add(in[l], in[r], k);
}
int change2(int l, int r)
{
int ans = 0;
while (top[l] != top[r])
{
if (dep[top[l]] < dep[top[r]])
{
swap(l, r);
}
res = 0;
query(in[top[l]], in[l]);
ans += res;
ans %= p;
l = fa[top[l]];
}
if(dep[l] > dep[r])
{
swap(l, r);
}
res = 0;
query(in[l], in[r]);
ans += res;
return ans % p;
}
int main()
{
cin >> n >> m >> r >> p;
for (int i = 1 ; i <= n ; i ++)
{
cin >> w[i];
}
for (int i = 1 ; i < n ; i ++)
{
int x, y;
cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs1(r, 0, 1);
dfs2(r, r);
sq = sqrt(n);
for (int i = 1 ; i <= n ; i ++)
{
int s = i / sq + 1;
if (!st[s])
{
st[s] = i;
}
ed[s] = i;
block[i] = s;
sum[s] += wt[i];
}
while (m --)
{
int opt;
cin >> opt;
if (opt == 1)
{
int x, y, z;
cin >> x >> y >> z;
change1(x, y, z);
}
else if (opt == 2)
{
int x, y;
cin >> x >> y;
cout << change2(x, y) << endl;
}
else if (opt == 3)
{
int x, z;
cin >> x >> z;
add(in[x], out[x], z);
}
else
{
int x;
cin >> x;
cout << query(in[x], out[x]) << endl;
}
}
return 0;
}