#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int SIZE=1e5+10;
int ls(int i){return i<<1;}
int rs(int i){return i<<1|1;}
int _max(int x,int y){return x>y?x:y;}
struct Edge{
int v,next;
}edge[2*SIZE];
int head[SIZE],cnt=1;
int data[SIZE],ndata[SIZE];
int fa[SIZE],deep[SIZE],size[SIZE],hson[SIZE];
int top[SIZE],dfn[SIZE],tot,p;
struct LT{
int l,r;
int sum,lz;
}line_tree[SIZE*4+10];
void build(int l,int r,int i){
line_tree[i].l=l,line_tree[i].r=r;
if(l==r){line_tree[i].sum=ndata[l];return ;}
int mid=(l+r)>>1;
build(l,mid,ls(i));
build(mid+1,r,rs(i));
line_tree[i].sum=(line_tree[ls(i)].sum+line_tree[rs(i)].sum)%p;
}
void lztage(int i){
line_tree[ls(i)].sum+=(line_tree[ls(i)].r-line_tree[ls(i)].l+1)*line_tree[i].lz;
line_tree[rs(i)].sum+=(line_tree[rs(i)].r-line_tree[rs(i)].r+1)*line_tree[i].lz;
line_tree[ls(i)].sum%=p;line_tree[rs(i)].sum%=p;
line_tree[ls(i)].lz+=line_tree[i].lz;line_tree[rs(i)].lz+=line_tree[i].lz;
line_tree[i].lz=0;
}
int search(int l,int r,int i){
if(line_tree[i].l>=l&&line_tree[i].r<=r) return line_tree[i].sum%p;
lztage(i);
int sum=0;
if(line_tree[ls(i)].r>=l) sum+=search(l,r,ls(i));
if(line_tree[rs(i)].l<=r) sum+=search(l,r,rs(i));
return sum%p;
}
void add(int l,int r,int i,int k){
if(line_tree[i].l>=l&&line_tree[i].r<=r)
{
line_tree[i].sum+=(line_tree[i].r-line_tree[i].l+1)*k;
line_tree[i].sum%=p;
line_tree[i].lz+=k;
return ;
}
lztage(i);
if(line_tree[ls(i)].r>=l) add(l,r,ls(i),k);
if(line_tree[rs(i)].l<=r) add(l,r,rs(i),k);
line_tree[i].sum=(line_tree[ls(i)].sum+line_tree[rs(i)].sum)%p;
}
int query1(int x,int y){
int ans=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
ans+=search(dfn[top[x]],dfn[x],1);
ans%=p;
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
ans+=search(dfn[x],dfn[y],1);
return ans%p;
}
void Tup1(int x,int y,int k){
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) swap(x,y);
add(dfn[top[x]],dfn[x],1,k);
x=fa[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
add(dfn[x],deep[y],1,k);
}
int query2(int root){
return search(dfn[root],dfn[root]+size[root]-1,1);
}
void Tup2(int root,int k){
add(dfn[root],dfn[root]+size[root]-1,1,k);
}
void add_edge(int x,int y){
edge[cnt].v=y;
edge[cnt].next=head[x];
head[x]=cnt++;
}
void dfs1(int u,int dep){
deep[u]=dep;
size[u]=1;
hson[u]=0;
for(int i=head[u];i;i=edge[i].next)
{
int v=edge[i].v;
if(deep[v]) continue;
dfs1(v,dep+1);
size[u]+=size[v];
fa[v]=u;
if(size[v]>size[hson[v]])
hson[u]=v;
}
}
void dfs2(int u,int t){
top[u]=t;
dfn[u]=++tot;
ndata[tot]=data[u];
if(!hson[u]) return ;
dfs2(hson[u],t);
for(int i=head[u];i;i=edge[i].next)
if(edge[i].v!=hson[u]&&edge[i].v!=fa[u]) dfs2(edge[i].v,edge[i].v);
}
int main(){
int n,m,r;
scanf("%d%d%d%d",&n,&m,&r,&p);
for(int i=1;i<=n;i++)
scanf("%d",&data[i]);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
}
size[0]=-1;
dfs1(r,1);
dfs2(r,r);
build(1,n,1);
while(m--)
{
int opt,x,y,z;
scanf("%d",&opt);
if(opt==1) scanf("%d%d%d",&x,&y,&z),Tup1(x,y,z);
if(opt==2) scanf("%d%d",&x,&y),printf("%d\n",query1(x,y)%p);
if(opt==3) scanf("%d%d",&x,&z),Tup2(x,z);
if(opt==4) scanf("%d",&x),printf("%d\n",query2(x)%p);
}
return 0;
}
感谢大佬