#include<bits/stdc++.h>
#define int long long
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
using namespace std;
const int N = 100010;
int n,m,root,p,cnt,val[N],son[N],id[N],fa[N],dep[N],size[N],top[N],chain[N];
vector<int> e[N];
struct node{
int l;
int r;
int sum;
int add;
}v[N<<2];
inline void dfs1(int now,int pre,int depth){
dep[now]=depth;
fa[now]=pre;
size[now]=1;
int maxson=-1;
for(auto &i:e[now]){
if(i==pre) continue;
dfs1(i,now,depth+1);
size[now]+=size[i];
if(size[i]>maxson){
maxson=size[i];
son[now]=i;
}
}
}
inline void dfs2(int now,int TOP){
cnt++;
id[now]=cnt;
chain[cnt]=val[now];
top[now]=TOP;
if(!son[now]) return;
else dfs2(son[now],TOP);
for(auto &i:e[now]){
if(i==son[now]||i==fa[now]) continue;
else dfs2(i,i);
}
}
inline void pushup(int pos){
v[pos].sum=v[lson(pos)].sum+v[rson(pos)].sum;
}
inline void pushdown_add(int pos,int num){
(v[pos].add+=num)%=p;
(v[pos].sum+=(v[pos].r-v[pos].l+1)*num)%=p;
}
inline void pushdown(int pos){
pushdown_add(lson(pos),v[pos].add);
pushdown_add(rson(pos),v[pos].add);
v[pos].add=0;
}
inline void build(int pos,int l,int r){
v[pos].l=l;
v[pos].r=r;
v[pos].add=0;
if(l==r){
v[pos].sum=chain[l];
return;
}
int mid=(l+r)>>1;
build(lson(pos),l,mid);
build(rson(pos),mid+1,r);
pushup(pos);
v[pos].sum%=p;
}
inline void Add(int pos,int ql,int qr,int num){
if(ql<=v[pos].l&&qr>=v[pos].r){
(v[pos].sum+=(v[pos].r-v[pos].l+1)*num)%=p;
(v[pos].add+=num)%=p;
return;
}
pushdown(pos);
int mid=(v[pos].l+v[pos].r)>>1;
if(ql<=mid) Add(lson(pos),ql,qr,num);
if(qr>mid) Add(rson(pos),ql,qr,num);
pushup(pos);
v[pos].sum%=p;
}
inline int Sum(int pos,int ql,int qr){
if(ql<=v[pos].l&&qr>=v[pos].r)
return v[pos].sum;
int sum=0;
int mid=(v[pos].l+v[pos].r)>>1;
pushdown(pos);
if(ql<=mid) (sum+=Sum(lson(pos),ql,qr))%=p;
if(qr>mid) (sum+=Sum(rson(pos),ql,qr))%=p;
return sum%p;
}
inline int ask1(int x,int y,int p){
int ans=0;
while(top[x]!=top[y]){
if(dep[x]<dep[y]) swap(x,y);
ans+=Sum(1,id[top[x]],id[x]);
ans%=p;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans+=Sum(1,id[x],id[y]);
return ans%p;
}
inline int add1(int x,int y,int num){
while(top[x]!=top[y]){
if(dep[x]<dep[y]) swap(x,y);
Add(1,id[top[x]],id[x],num);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
Add(1,id[x],id[y],num);
}
signed main(){
//cin.tie(0);
//ios::sync_with_stdio(0);
/*freopen("1.in","r",stdin);
freopen("1.out","w",stdout);*/
cin>>n>>m>>root>>p;
for(int i=1;i<=n;i++)
cin>>val[i];
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
e[x].push_back(y);
e[y].push_back(x);
}
dfs1(root,0,1);
dfs2(root,root);
build(1,1,n);
for(int i=1;i<=m;i++){
int opt,x,y,z;
cin>>opt;
if(opt==1){
cin>>x>>y>>z;
add1(x,y,z);
}
else if(opt==2){
cin>>x>>y;
cout<<ask1(x,y,p)%p<<"\n";
}
else if(opt==3){
cin>>x>>z;
Add(1,id[x],id[x]+size[x]-1,z);
}
else if(opt==4){
cin>>x;
cout<<Sum(1,id[x],id[x]+size[x]-1)%p<<"\n";
}
}
//fclose(stdin);fclose(stdout);
return 0;
}