#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
long long n,m,r,p,a,b,c,d,val[MAXN],val2[MAXN],fa[MAXN],size[MAXN];
long long hs[MAXN],depth[MAXN],CNT=0,dfn[MAXN],head[MAXN];
vector<long long> edge[MAXN];
void dfs1(long long nood,long long father){
size[nood] = 1;
fa[nood] = father;
depth[nood] = depth[father]+1;
long long maxn=-1;
for(int i=0;i<edge[nood].size();i++){
int next = edge[nood][i];
if(next == father){
continue;
}
dfs1(next,nood);
size[nood] += size[next];
if(size[next]>maxn){
maxn = size[next];
hs[nood] = next;
}
}
}
void dfs2(long long nood,long long fa){
dfn[nood] = ++CNT;
val2[dfn[nood]] =val[nood];
if(hs[nood]){head[hs[nood]] = head[nood];
dfs2(hs[nood],nood);
}
for(int i=0;i<edge[nood].size();i++){
long long next = edge[nood][i];
if(next == fa || next == hs[nood]){
continue;
}
dfs2(next,nood);
head[next] = next;
}
}
struct node{
int l,r;
long long dat;
long long tag;
};
node ST[4*MAXN];
void build(int node_num,int l,int r){
ST[node_num].l = l;
ST[node_num].r = r;
ST[node_num].tag = 0ll;
if(l==r){
ST[node_num].dat = val2[l];return;
}
build(2*node_num,l,(l+r)/2);
build(2*node_num+1,(l+r)/2+1,r);
ST[node_num].dat = ST[2*node_num].dat+ST[2*node_num+1].dat;
}
void push_down(int node_num){
if(ST[node_num].tag==0)return;
int mid = (ST[node_num].l + ST[node_num].r)/2;
ST[node_num*2].dat += ST[node_num].tag * (mid-ST[node_num].l+1);
ST[node_num*2].tag += ST[node_num].tag;
ST[node_num*2+1].dat += ST[node_num].tag * (ST[node_num].r-mid);
ST[node_num*2+1].tag += ST[node_num].tag;
ST[node_num*2].dat %= p;
ST[node_num*2].tag %= p;
ST[node_num*2+1].dat %= p;
ST[node_num*2+1].tag %= p;
ST[node_num].tag=0;
}
long long ask(int node_num,int tl,int tr){
int mid = (ST[node_num].l + ST[node_num].r)/2;
if(tl<=ST[node_num].l && ST[node_num].r<=tr){
return ST[node_num].dat%p;
}
push_down(node_num);
long long res = 0;
if(mid>=tl) res+=ask(node_num*2,tl,tr);
if(mid<tr) res+=ask(node_num*2+1,tl,tr);
return res%p;
}
void add(int node_num,int tl,int tr,long long val){
if(tl<=ST[node_num].l && ST[node_num].r<=tr){
ST[node_num].dat += val*(ST[node_num].r - ST[node_num].l+1);
ST[node_num].tag += val;
ST[node_num].dat %=p;
ST[node_num].tag %=p;
return ;
}
int mid = (ST[node_num].l + ST[node_num].r)/2;
push_down(node_num);
if(mid>=tl) add(node_num*2,tl,tr,val);
if(mid<tr) add(node_num*2+1,tl,tr,val);
ST[node_num].dat = (ST[2*node_num].dat+ST[2*node_num+1].dat)%p;
}
void f1(int x,int y,int z){
while(head[x]!=head[y]){
if(depth[head[x]] > depth[head[y]])swap(x,y);
add(1,dfn[head[y]],dfn[y],z);
y = fa[head[y]];
}
if(dfn[x] < dfn[y])swap(x,y);
add(1,dfn[y],dfn[x],z);
}
long long f2(int x,int y){
long long ans=0;
while(head[x]!=head[y]){
if(depth[head[x]] > depth[head[y]])swap(x,y);
ans = (ans + ask(1,dfn[head[y]],dfn[y]))%p;
y = fa[head[y]];
}
if(dfn[x] < dfn[y])swap(x,y);
ans = (ans + ask(1,dfn[y],dfn[x]))%p;
return ans;
}
void f3(int x,int z){
add(1,dfn[x],dfn[x]+size[x]-1,z);
}
long long f4(int x){
return ask(1,dfn[x],dfn[x]+size[x]-1)%p;
}
int main(){
cin>>n>>m>>r>>p;
for(int i=1;i<=n;i++){
cin>>val[i];
}
for(int i=0;i<n-1;i++){
cin>>a>>b;
edge[a].push_back(b);
edge[b].push_back(a);
}
dfs1(r,0);
head[r] = r;
dfs2(r,0);
build(1,1,n);
for(int i=0;i<m;i++){
cin>>a;
if(a==1){
cin>>b>>c>>d;
f1(b,c,d);
}
else if(a==2){
cin>>b>>c;
cout<<f2(b,c)<<'\n';
}
else if(a==3){
cin>>b>>c;
f3(b,c);
}
else {
cin>>b;
cout<<f4(b)<<'\n';
}
}
return 0;
}
28pts 一个警示后人都没用上