#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define Z(a) (a%p);
#define Swap(a,b) a^=b,b^=a,a^=b
const int N = 2e5+5;
int dfn[N],rex[N],dep[N],son[N],top[N],fa[N],siz[N];
LL tr[4*N],add[4*N];
int n,m,root,p,a[N];
vector<int>v[N];
inline int read(){int x=0;char c=getchar();while(c<'0'||c>'9'){c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}return x;}
void dfs(int k,int fath){
siz[k] = 1;
for(int i = 0;i < v[k].size();++i){
int u = v[k][i];
if(u == fath)continue;
dep[u]=dep[k]+1;fa[u] = k;
dfs(u,k);
siz[k] += siz[u];
if(siz[u] > siz[son[k]])son[k]=u;
}
}
void dfs1(int k,int fath){
dfn[k] = ++dfn[0];rex[dfn[0]] = k;
if(!son[k])return;
top[son[k]] = top[k];
dfs1(son[k],k);
for(int i = 0;i < v[k].size();++i){
int u = v[k][i];
if(u == fath || u == son[k])continue;
top[u] = u;
dfs1(u,k);
}
}
void push_down(int k,int l,int r){
int mid = l+r>>1;
add[2*k] = Z(add[k]+add[2*k]);
add[2*k+1] = Z(add[k]+add[2*k+1]);
tr[2*k] = Z(tr[2*k]+add[k]*(mid-l+1));
tr[2*k+1] = Z(tr[2*k+1]+add[k]*(r-mid));
add[k] = 0;
}
void build(int k,int l,int r){
if(l == r){tr[k] = Z(a[rex[l]]);return;}
int mid = l+r>>1;
build(2*k,l,mid);build(2*k+1,mid+1,r);
tr[k] = Z(tr[2*k]+tr[2*k+1]);
}
void ad(int k,int l,int r,int sl,int sr,int f){
if(l >= sl && r <= sr){
add[k] = Z(add[k]+f);
tr[k] = Z(tr[k]+f*(r-l+1));
return;
}
if(r < sl || sr < l)return;
push_down(k,l,r);
int mid = l+r>>1;
if(sl <= mid)ad(2*k,l,mid,sl,sr,f);
if(mid < sr)ad(2*k+1,mid+1,r,sl,sr,f);
tr[k] = Z(tr[2*k]+tr[2*k+1]);
}
LL query(int k,int l,int r,int sl,int sr){
if(l >= sl && r <= sr){return tr[k];}
if(r < sl || sr < l)return 0;
push_down(k,l,r);
int mid = l+r>>1;
LL ret=0;
if(sl <= mid)ret=Z(ret+query(2*k,l,mid,sl,sr));
if(mid < sr)ret=Z(ret+query(2*k+1,mid+1,r,sl,sr));
return ret;
}
void Treeadd(int x,int y,int f){
int fx = top[x],fy = top[y];
while(fx!=fy){
if(dep[fx] < dep[fy])Swap(x,y),Swap(fx,fy);
ad(1,1,n,dfn[fx],dfn[x],f);
x = fa[x],fx = top[x];
}if(dep[x] < dep[y])Swap(x,y);
ad(1,1,n,dfn[y],dfn[x],f);
}
LL queryTree(int x,int y){
LL sum = 0;
int fx = top[x],fy = top[y];
while(fx!=fy){
if(dep[fx] < dep[fy])Swap(fx,fy),Swap(x,y);
sum = Z(sum+query(1,1,n,dfn[fx],dfn[x]));
x = fa[fx],fx = top[x];
}if(dep[x] < dep[y])Swap(x,y);
sum = Z(sum+query(1,1,n,dfn[y],dfn[x]));
return sum;
}
LL Tquery(int x){
return query(1,1,n,dfn[x],dfn[x]+siz[x]-1);
}
void Tad(int x,int f){
ad(1,1,n,dfn[x],dfn[x]+siz[x]-1,f);
}
int main(){
freopen("1.txt","w",stdout);
n=read();m=read();root=read();p=read();
for(register int i = 1;i <= n;++i)a[i]=read();
for(register int i = 1;i <= n-1;++i){
int x=read(),y=read();
v[x].push_back(y);
v[y].push_back(x);
}
dfs(root,0);
top[root] = root;
dfs1(root,0);
build(1,1,n);
int x,y,op,z;
while(m--){
op=read();
if(op==1){
x=read(),y=read(),z=read();
Treeadd(x,y,z%p);
}
if(op==2){
x=read(),y=read();
printf("%lld\n",queryTree(x,y));
}
if(op==3){
x=read(),z=read();
Tad(x,z%p);
}
if(op==4){
x=read();
printf("%lld\n",Tquery(x));
}
}
return 0;
}