#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct tree{
ll sum,lazy;
ll l,r;
tree *left,*right;
}*root;
ll n,m,r,p,d;
vector<ll> v[114514];
ll fa[114514],dep[114514],son[114514],sum[114514],top[114514],ID[114514],a[114514];
ll b[114514];
void dfs1(ll id,ll f){
fa[id]=f;
dep[id]=dep[f]+1;
sum[id]=1;
for(int i=0;i<int(v[id].size());i++){
if(v[id][i]==f)continue;
dfs1(v[id][i],id);
sum[id]+=sum[v[id][i]];
if(sum[v[id][i]]>sum[son[id]]){
son[id]=v[id][i];
}
}
}void dfs2(ll id,bool z){
if(z){
top[id]=top[fa[id]];
}else{
top[id]=id;
}ID[id]=++d;
a[d]=b[id];
if(son[id])dfs2(son[id],1);
for(int i=0;i<int(v[id].size());i++){
if(v[id][i]==fa[id] || v[id][i]==son[id]){
continue;
}dfs2(v[id][i],0);
}
}void build(tree *&t,ll l,ll r){
if(t==NULL)t=new tree;
t->l=l;
t->r=r;
t->lazy=0;
if(l==r){
t->left=NULL;
t->right=NULL;
t->sum=a[l]%p;
return;
}int mid=(l+r)>>1;
build(t->left,l,mid);
build(t->right,mid+1,r);
t->sum=t->left->sum+t->right->sum;
t->sum%=p;
}void push_down(tree *t){
if(t->left!=NULL){
t->left->sum+=(t->left->r-t->left->r+1)%p*t->lazy;
t->left->lazy+=t->lazy;
t->left->sum%=p;
t->left->lazy%=p;
t->right->sum+=(t->right->r-t->right->r+1)%p*t->lazy;
t->right->lazy+=t->lazy;
t->right->sum%=p;
t->right->lazy%=p;
}t->lazy=0;
}void add(tree *t,ll l,ll r,ll d){
push_down(t);
if(t->l>=l && t->r<=r){
t->sum+=d*(t->r-t->l+1);
t->lazy+=d;
t->sum%=p;
t->lazy%=p;
return;
}if(t->left->r>=l){
add(t->left,l,r,d);
}if(t->right->l<=r){
add(t->right,l,r,d);
}t->sum=t->left->sum+t->right->sum;
t->sum%=p;
}int query(tree *t,ll l,ll r){
if(t->l>=l && t->r<=r){
return t->sum;
}push_down(t);
ll sumi=0;
if(t->left->r>=l){
sumi+=query(t->left,l,r);
}if(t->right->l<=r){
sumi+=query(t->right,l,r);
}return sumi%p;
}int tree_query1(ll i,ll j){
ll sumi=0;
while(top[i]!=top[j]){
if(dep[top[i]]<dep[top[j]])swap(i,j);
sumi+=query(root,ID[top[i]],ID[i]);
sumi%=p;
i=fa[top[i]];
}sumi+=query(root,min(ID[i],ID[j]),max(ID[i],ID[j]));
sumi%=p;
return sumi;
}int tree_query2(ll u){
return query(root,ID[u],ID[u]+sum[u]-1);
}void tree_add1(ll i,ll j,ll d){
while(top[i]!=top[j]){
if(dep[top[i]]<dep[top[j]])swap(i,j);
add(root,ID[top[i]],ID[i],d);
i=fa[top[i]];
}add(root,min(ID[i],ID[j]),max(ID[i],ID[j]),d);
}void tree_add2(ll u,ll d){
return add(root,ID[u],ID[u]+sum[u]-1,d);
}int main(){
ios::sync_with_stdio(0);
cout.tie(0);cin.tie(0);
cin>>n>>m>>r>>p;
for(int i=1;i<=n;i++){
cin>>b[i];
}for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}dfs1(r,0);
dfs2(r,0);
build(root,1,n);
while(m--){
int op;
cin>>op;
if(op==1){
int x,y,z;
cin>>x>>y>>z;
tree_add1(x,y,z);
}else if(op==2){
int x,y;
cin>>x>>y;
cout<<tree_query1(x,y)<<'\n';
}else if(op==3){
int x,y;
cin>>x>>y;
tree_add2(x,y);
}else{
int x;
cin>>x;
cout<<tree_query2(x)<<'\n';
}
}
return 0;
}
本地运行停止工作,在线运行输出一半