#include<vector>
#include<iostream>
#define ll long long
using namespace std;
ll mod;
vector<ll> edge[100001];
vector<ll> sons[100001];
ll heachd[100001];
ll sonnum[100001];
ll fa[100001][20];
ll linhd[100001];
ll dfn[100001];
ll dfout[100001];
ll dfd=0;
ll dep[100001];
ll log[20];
ll n,m,r,p;
ll df[100001];
struct node{
ll lt,rt,lazy;
ll lc,rc;
ll val;
};
node tree[400001];
class SegTree{
private:
vector<ll> a;
ll n;
ll treesize=0;
public:
SegTree(){
}
SegTree(ll _a[],ll _n){
n=_n;
for(ll i=0;i<n;i++){
a.push_back(_a[i]);
}
}
~SegTree(){
}
ll build(ll l,ll r){
if(l==r){
node t;
t.lt=l;
t.rt=r;
t.val=a[l];
t.lazy=0;
tree[treesize]=t;
treesize++;
return treesize-1;
}
else{
node t;
t.lt=l;
t.rt=r;
t.lazy=0;
tree[treesize]=t;
treesize++;
ll ret=treesize-1;
tree[ret].lc=build(l,(l+r)/2);
tree[ret].rc=build((l+r)/2+1,r);
tree[ret].val=tree[tree[ret].lc].val+tree[tree[ret].rc].val;
return ret;
}
}
void mark(ll cur,ll k){
tree[cur].lazy+=k;
tree[cur].lazy%=mod;
tree[cur].val+=k%mod*(tree[cur].rt-tree[cur].lt+1)%mod;
tree[cur].val%=mod;
}
void pushdown(ll cur){
tree[tree[cur].lc].lazy+=tree[cur].lazy;
tree[tree[cur].lc].val+=tree[cur].lazy*(tree[tree[cur].lc].rt+1-tree[tree[cur].lc].lt);
tree[tree[cur].rc].lazy+=tree[cur].lazy;
tree[tree[cur].rc].val+=tree[cur].lazy*(tree[tree[cur].rc].rt+1-tree[tree[cur].rc].lt);
tree[tree[cur].lc].lazy%=mod;
tree[tree[cur].lc].val%=mod;
tree[tree[cur].rc].lazy%=mod;
tree[tree[cur].rc].val%=mod;
tree[cur].lazy=0;
}
void plus(ll l,ll r,ll cur,ll k){
if(tree[cur].lt>=l&&tree[cur].rt<=r){
mark(cur,k);
return;
}
if(tree[cur].rt<l||tree[cur].lt>r){
return;
}
plus(l,r,tree[cur].lc,k);
plus(l,r,tree[cur].rc,k);
tree[cur].val=tree[tree[cur].lc].val+tree[tree[cur].rc].val;
tree[cur].val+=tree[cur].lazy*(tree[cur].rt-tree[cur].lt+1);
tree[cur].val%=mod;
}
ll query(ll l,ll r,ll cur){
if(tree[cur].lt>=l&&tree[cur].rt<=r){
return tree[cur].val;
}
if(tree[cur].rt<l||tree[cur].lt>r){
return 0;
}
pushdown(cur);
return (query(l,r,tree[cur].lc)+query(l,r,tree[cur].rc))%mod;
}
};
void dfs(ll now,ll fat,ll depth){
dep[now]=depth;
heachd[now]=-1;
ll machd=-1;
ll sumson=0;
for(ll i=1;i<=19;i++){
if(log[i]<=dep[now]){
fa[now][i]=fa[fa[now][i-1]][i-1];
}
}
for(ll i=0;i<edge[now].size();i++){
if(edge[now][i]!=fat){
sons[now].push_back(edge[now][i]);
fa[ (ll)(edge[now][i]) ][0]=now;
dfs(edge[now][i],now,depth+1);
if(sonnum[edge[now][i]]>machd){
machd=sonnum[edge[now][i]];
heachd[now]=edge[now][i];
}
sumson+=sonnum[edge[now][i]];
}
}
sonnum[now]=sumson+1;
}
void hl(ll now,ll top){
linhd[now]=top;
dfn[now]=dfd;
df[dfd]=now;
dfd++;
if(heachd[now]!=-1){
hl(heachd[now],top);
}
for(ll i=0;i<sons[now].size();i++){
if(sons[now][i]!=heachd[now])hl(sons[now][i],sons[now][i]);
}
dfout[now]=dfd-1;
}
ll lca(ll a,ll b){
if(dep[a]<dep[b]){
ll t=a;
a=b;
b=t;
}
for(ll i=19;i>=0;i--){
if(dep[a]-dep[b]>=log[i]){
a=fa[a][i];
}
}
if(a==b){
return a;
}
for(ll i=19;i>=0;i--){
if(dep[a]>=log[i]&&fa[a][i]!=fa[b][i]){
a=fa[a][i];
b=fa[b][i];
}
}
a=fa[a][0];
b=fa[b][0];
return a;
}
ll inp[100001];
ll a[100001];
SegTree segtree;
void input(){
log[0]=1;
for(ll i=1;i<20;i++){
log[i]=2*log[i-1];
}
cin>>n>>m>>r>>p;
mod=p;
for(ll i=0;i<n;i++) cin>>a[i];
for(ll i=0;i<n-1;i++){
ll t1,t2;
cin>>t1>>t2;
t1--;
t2--;
edge[t1].push_back(t2);
edge[t2].push_back(t1);
}
dfs(r-1,-1,0);
hl(r-1,r-1);
for(ll i=0;i<n;i++){
inp[i]=a[df[i]];
}
segtree=SegTree(inp,n);
segtree.build(0,n-1);
}
void solve(){
while(m--){
ll op;
cin>>op;
if(op==1){
ll t1,t2,t3;
cin>>t1>>t2>>t3;
t1--;
t2--;
ll te=lca(t1,t2);
while(linhd[t1]!=linhd[te]){
segtree.plus(dfn[linhd[t1]],dfn[t1],0,t3);
t1=fa[linhd[t1]][0];
}
while(linhd[t2]!=linhd[te]){
segtree.plus(dfn[linhd[t2]],dfn[t2],0,t3);
t2=fa[linhd[t2]][0];
}
segtree.plus(min(dfn[t1],dfn[t2]),max(dfn[t1],dfn[t2]),0,t3);
}
if(op==2){
ll t1,t2;
cin>>t1>>t2;
t1--;
t2--;
ll out=0;
ll te=lca(t1,t2);
while(linhd[t1]!=linhd[te]){
out+=segtree.query(dfn[linhd[t1]],dfn[t1],0);
t1=fa[linhd[t1]][0];
}
while(linhd[t2]!=linhd[te]){
out+=segtree.query(dfn[linhd[t2]],dfn[t2],0);
t2=fa[linhd[t2]][0];
}
out+=segtree.query(min(dfn[t1],dfn[t2]),max(dfn[t1],dfn[t2]),0);
cout<<out<<'\n';
}
if(op==3){
ll t1,t2;
cin>>t1>>t2;
t1--;
segtree.plus(dfn[t1],dfout[t1],0,t2);
}
if(op==4){
ll t1;
cin>>t1;
t1--;
cout<<segtree.query(dfn[t1],dfout[t1],0)<<'\n';
}
}
}
int main(){
input();
solve();
}