代码如下:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>
inline T Min(T x,T y){
return x<y?x:y;
}
template<class T>
inline T Max(T x,T y){
return y<x?x:y;
}
template<class T>
inline void Swap(T &x,T &y){
T tmp=x;
x=y,y=tmp;
}
inline int read(){
int x=0,f=1;char ch=getchar();
while('0'>ch||'9'<ch){if(ch=='-') f=-f;ch=getchar();}
while('0'<=ch&&'9'>=ch){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
const int MAXN=100005;
struct LS{
int HEAD[MAXN],nxt[MAXN<<2],edge[MAXN<<2],tot;
inline void add(int u,int v){
edge[++tot]=v,nxt[tot]=HEAD[u],HEAD[u]=tot;
}
inline int head(int u){
return HEAD[u];
}
inline int nex(int i){
return nxt[i];
}
inline int operator[](int i){
return edge[i];
}
inline void clear(){
memset(HEAD,0,sizeof HEAD);
tot=0;
}
};
LS G;
int arr[MAXN];
int n=read(),m=read(),root=read(),M=read();
int siz[MAXN],son[MAXN],fa[MAXN],dep[MAXN];
inline void dfs1(int u){
siz[u]=1,son[u]=-1;
for(int i=G.head(u);i;i=G.nex(i)){
int v=G[i];
if(v==fa[u]) continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs1(v);
siz[u]+=siz[v];
if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v;
}
}
int top[MAXN],dfn[MAXN],rnk[MAXN],cnt;
inline void dfs2(int u,int t){
top[u]=t;
dfn[u]=++cnt;
rnk[cnt]=u;
if(son[u]==-1) return;
dfs2(son[u],t);
for(int i=G.head(u);i;i=G.nex(i)) if(G[i]!=son[u]&&G[i]!=fa[u]) dfs2(G[i],G[i]);
}
struct ST{
int sum[MAXN<<2],lazy[MAXN<<2];
inline void get(int rt){
sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%M;
}
inline void build(int rt,int l,int r){
if(l==r){
sum[rt]=arr[dfn[l]]%M;
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
get(rt);
}
inline void push_down(int rt,int l,int r,int mid){
lazy[rt<<1]=(lazy[rt<<1]+lazy[rt])%M,lazy[rt<<1|1]=(lazy[rt<<1|1]+lazy[rt])%M;
sum[rt<<1]=(sum[rt<<1]+lazy[rt]*(mid-l+1))%M,sum[rt<<1|1]=(sum[rt<<1|1]+lazy[rt]*(r-mid))%M;
lazy[rt]=0;
}
inline void updata(int rt,int l,int r,const int &L,const int &R,const int &val){
if(L<=l&&r<=R){
lazy[rt]=(lazy[rt]+val)%M;
sum[rt]=(sum[rt]+val*(r-l+1))%M;
return;
}
int mid=(l+r)>>1;
if(lazy[rt]) push_down(rt,l,r,mid);
if(L<=mid) updata(rt<<1,l,mid,L,R,val);
if(R>mid) updata(rt<<1|1,mid+1,r,L,R,val);
get(rt);
}
inline int query(int rt,int l,int r,const int &L,const int &R){
if(L<=l&&r<=R) return sum[rt];
int mid=(l+r)>>1;
if(lazy[rt]) push_down(rt,l,r,mid);
int ret=0;
if(L<=mid) ret=(ret+query(rt<<1,l,mid,L,R))%M;
if(R>mid) ret=(ret+query(rt<<1|1,mid+1,r,L,R))%M;
return ret;
}
};
ST t;
inline void change_road(int u,int v,int w){
w%=M;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) Swap(u,v);
t.updata(1,1,n,dfn[top[u]],dfn[u],w);
u=fa[top[u]];
}
if(dep[u]>dep[v]) Swap(u,v);
t.updata(1,1,n,dfn[u],dfn[v],w);
}
inline void change_tree(int u,int w){
t.updata(1,1,n,dfn[u],dfn[u]+siz[u]-1,w);
}
inline int query_road(int u,int v){
int ret=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) Swap(u,v);
ret=(ret+t.query(1,1,n,dfn[top[u]],dfn[u]))%M;
u=fa[top[u]];
}
if(dep[u]>dep[v]) Swap(u,v);
return (ret+t.query(1,1,n,dfn[u],dfn[v]))%M;
}
inline int query_tree(int u){
return t.query(1,1,n,dfn[u],dfn[u]+siz[u]-1)%M;
}
int main(){
for(int i=1;i<=n;i++) arr[i]=read();
for(int i=1;i<n;i++){
int u=read(),v=read();
G.add(u,v),G.add(v,u);
}
dfs1(root),dfs2(root,root);
t.build(1,1,n);
for(;m--;){
int op=read();
if(op==1){
int x=read(),y=read(),z=read();
change_road(x,y,z);
}
else if(op==2){
int x=read(),y=read();
printf("%d\n",query_road(x,y));
}
else if(op==3){
int x=read(),z=read();
change_tree(x,z);
}
else{
int x=read();
printf("%d\n",query_tree(x));
}
}
return 0;
}