#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int maxm=2e5+5;
#define lson node<<1
#define rson node<<1|1
int n,m,r,mod,idx;
int head[maxn],w[maxm],v[maxm],nex[maxm],cnt,son[maxn],size[maxn],dep[maxn],top[maxn];
int fa[maxn];
int p[maxn],id[maxn],pre[maxn];
struct node{
int l,r,val,lazy;
}t[maxn<<2];
void add(int x,int y){
v[++cnt]=y;
nex[cnt]=head[x];
head[x]=cnt;
}
void dfs(int u,int f,int deep){
dep[u]=deep;
size[u]=1;
fa[u]=f;
int maxx=-1;
for(int i=head[u];i;i=nex[i]){
int to=v[i];
if(f==to) continue;
dfs(to,u,deep+1);
size[u]+=size[to];
if(size[to]>maxx) {maxx=size[to];son[u]=to;}
}
}
void dfs2(int node,int tope){
id[node]=++idx;
pre[idx]=node;
top[node]=tope;
if(!son[node]) return;
dfs2(son[node],tope);
for(int i=head[node];i;i=nex[i]){
int to=v[i];
if(to==fa[node]||to==son[node]) continue;
dfs2(to,to);
}
}
//开始线段树
void pushup(int node){
t[node].val=(t[lson].val+t[rson].val)%mod;
}
void spread(int node){
if(t[node].lazy){
t[lson].lazy=(t[lson].lazy+t[node].lazy)%mod;
t[rson].lazy=(t[rson].lazy+t[node].lazy)%mod;
t[lson].val=(t[lson].val+t[node].lazy*(t[lson].r-t[lson].l+1))%mod;
t[rson].val=(t[rson].val+t[node].lazy+(t[rson].r-t[rson].l+1))%mod;
t[node].lazy=0;
}
}
void build(int start,int end,int node){
t[node].l=start,t[node].r=end;
if(start==end){
t[node].val=p[pre[start]];
return;
}
int mid=start+end>>1;
build(start,mid,lson);
build(mid+1,end,rson);
pushup(node);
}
void update(int start,int end,int node,int k){
int l=t[node].l,r=t[node].r;
if(start<=l&&r<=end){
t[node].lazy+=k;
t[node].val=(t[node].val+k*(r-l+1))%mod;
return;
}
spread(node);
int mid=l+r>>1;
if(start<=mid) update(start,end,lson,k);
if(end>mid) update(start,end,rson,k);
pushup(node);
}
int query(int start,int end,int node){
int l=t[node].l,r=t[node].r;
if(start<=l&&r<=end){
return t[node].val;
}
spread(node);
int ans=0;
int mid=l+r>>1;
if(start<=mid) ans+=query(start,end,lson);
if(end>mid) ans+=query(start,end,rson);
return ans%mod;
}
void myupdate(int x,int y,int k){
k%=mod;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(id[top[x]],id[x],1,k);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
update(id[x],id[y],1,k);
}
int myquery(int x,int y){
int ans=0;
while (top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans+=query(id[top[x]],id[x],1);
ans%=mod;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans+= query(id[x],id[y],1);
return ans%mod;
}
void treeupdate(int x,int k){
update(id[x],id[x]+size[x]-1,1,k);
}
int treequery(int x){
return query(id[x],id[x]+size[x]-1,1);
}
int main(){
cin>>n>>m>>r>>mod;
for(int i=1;i<=n;i++) cin>>p[i];
for(int i=1;i<=n-1;i++){
int x,y;
cin>>x>>y;
add(x,y);add(y,x);
}
dfs(r,0,1);
dfs2(r,r);
build(1,n,1);
while(m--){
int op,x,y,z;
cin>>op;
if(op==1){
cin>>x>>y>>z;
myupdate(x,y,z);
}
if(op==2){
cin>>x>>y;
cout<<myquery(x,y)<<endl;
}
if(op==3){
cin>>x>>z;
treeupdate(x,z);
}
if(op==4){
cin>>x;
cout<<treequery(x)<<endl;
}
}
}
每个样例都比答案多了1,不知道为什么