悬关
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,r,mod;
struct Edge{int to,next;}e[N<<1];
int head[N<<1],cnt;
void init(){
for(int i=0;i<2*N;i++){
e[i].next=-1;
head[i]=-1;
}
cnt=0;
}
void addedge(int u,int v){
e[cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt++;
}
int ls(int x){return x<<1;}
int rs(int x){return x<<1|1;}
int w[N],w_new[N];
int tree[N<<2],tag[N<<2];
void addtag(int p,int pl,int pr,int d){
tag[p]+=d;
tree[p]+=d*(pr-pl+1);
tree[p]%=mod;
}
void push_up(int p){tree[p]=(tree[ls(p)]+tree[rs(p)])%mod;}
void push_down(int p,int pl,int pr){
if(tag[p]){
int mid=(pl+pr)>>1;
addtag(ls(p),pl,mid,tag[p]);
addtag(rs(p),mid+1,pr,tag[p]);
tag[p]=0;
}
}
void build(int p,int pl,int pr){
tag[p]=0;
if(pl==pr){
tree[p]=w_new[p];
tree[p]%=mod;
return ;
}
int mid=(pl+pr)>>1;
build(ls(p),pl,mid);
build(rs(p),mid+1,pr);
push_up(p);
}
void upd(int L,int R,int p,int pl,int pr,int d){
if(L<=pl&&pr<=R){addtag(p,pl,pr,d);return ;}
push_down(p,pl,pr);
int mid=(pl+pr)>>1;
if(L<=mid)upd(L,R,ls(p),pl,mid,d);
if(R>mid)upd(L,R,rs(p),mid+1,pr,d);
push_up(p);
}
int query(int L,int R,int p,int pl,int pr){
if(L<=pl&&pr<=R)return tree[p]%=mod;
push_down(p,pl,pr);
int res=0;
int mid=(pl+pr)>>1;
if(L<=mid)res+=query(L,R,ls(p),pl,mid);
if(R>mid)res+=query(L,R,rs(p),mid+1,pr);
return res;
}
int son[N],id[N],fa[N],dep[N],siz[N],top[N];
void dfs1(int u,int fat){
dep[u]=dep[fat]+1;
fa[u]=fat;
siz[u]=1;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v==fat)continue;
fa[v]=u;
dfs1(v,u);
siz[u]+=siz[v];
if((!son[u])||siz[son[u]]<siz[v])son[u]=v;
}
}
int num=0;
void dfs2(int x,int topx){
id[x]=++num;
w_new[num]=w[x];
top[x]=topx;
if(!son[x])return ;
dfs2(son[x],topx);
for(int i=head[x];~i;i=e[i].next){
int v=e[i].to;
if(v!=fa[x]&&v!=son[x])dfs2(v,v);
}
}
void updr(int x,int y,int z){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
upd(id[top[x]],id[x],1,1,n,z);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
upd(id[x],id[y],1,1,n,z);
}
int quer(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,1,n);
ans%=mod;
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans+=query(id[x],id[y],1,1,n);
return ans%mod;
}
void upd_tre(int x,int k){upd(id[x],id[x]+siz[x]-1,1,1,n,k);}
int query_tree(int x){return query(id[x],id[x]+siz[x]-1,1,1,n)%mod;}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
init();
cin>>n>>m>>r>>mod;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
addedge(u,v);
addedge(v,u);
}
dfs1(r,0);
dfs2(r,r);
build(1,1,n);
while(m--){
int k,x,y,z;
cin>>k;
if(k==1){cin>>x>>y>>z;updr(x,y,z);}
else if(k==2){cin>>x>>y;cout<<quer(x,y)<<'\n';}
else if(k==3){cin>>x>>y;upd_tre(x,y);}
else if(k==4){cin>>x;cout<<query_tree(x)<<'\n';}
}
return 0;
}