代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,r,p;
int dep[114514];
int fa[114514];
int son[114514];
int siz[114514];
int top[114514],dfn[114514],rev[114514],cnt;
int a[114514],w[114514*4];
int lzy[114514*4];
vector<int> tree[114514];
void dfs1(int u,int father){
fa[u]=father;
siz[u]=1;
dep[u]=dep[father]+1;
for(int i=0;i<tree[u].size();i++){
int v=tree[u][i];
if(v==father) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v]) son[u]=v;
}
}
void dfs2(int u,int t){
top[u]=t;
dfn[u]=++cnt;
rev[cnt]=u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i=0;i<tree[u].size();i++){
int v=tree[u][i];
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
void pushup(int u){
w[u]=(w[u*2]+w[u*2+1])%p;
}
void maketag(int u,int len,int x){
lzy[u]=(lzy[u]+x)%p;
w[u]=(w[u]+len*x)%p;
}
void pushdown(int u,int l,int r){
int mid=(l+r)/2;
maketag(u*2,mid-l+1,lzy[u]);
maketag(u*2+1,r-mid,lzy[u]);
lzy[u]=0;
}
void build(const int u,int l,int r){
if(l==r){
w[u]=a[rev[l]]%p;
return;
}
int mid=(l+r)/2;
build(u*2,l,mid),build(u*2+1,mid+1,r);
pushup(u);
}
bool InRange(int L,int R,int l,int r){
return (l<=L)&&(R<=r);
}
bool OutofRange(int L,int R,int l,int r){
return (L>r)||(R<l);
}
int query(int u,int L,int R,int l,int r){
if(InRange(L,R,l,r)) return w[u];
else if(!OutofRange(L,R,l,r)){
int mid=(L+R)/2;
pushdown(u,L,R);
return (query(u*2,L,mid,l,r)+query(u*2+1,mid+1,R,l,r))%p;
}
else return 0;
}
void update(int u,int L,int R,int l,int r,int x){
if(InRange(L,R,l,r)) maketag(u,R-L+1,x);
else if(!OutofRange(L,R,l,r)){
int mid=(L+R)/2;
pushdown(u,L,R);
update(u*2,L,mid,l,r,x);
update(u*2+1,mid+1,R,l,r,x);
pushup(u);
}
else return;
}
int qry(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=(ans+query(1,1,n,dfn[top[x]],dfn[x]))%p;
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans=(ans+query(1,1,n,dfn[x],dfn[y]))%p;
return ans;
}
void upd(int x,int y,int k){
k%=p;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(1,1,n,dfn[top[x]],dfn[x],k);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
update(1,1,n,dfn[x],dfn[y],k);
}
signed main(){
cin>>n>>m>>r>>p;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n-1;i++){
int x,y;
cin>>x>>y;
tree[x].push_back(y);
tree[y].push_back(x);
}
dfs1(r,0);
dfs2(r,r);
build(1,1,n);
while(m--){
int op,x,y,z;
cin>>op;
if(op==1){
cin>>x>>y>>z;
upd(x,y,z);
}
else if(op==2){
cin>>x>>y;
cout<<qry(x,y)<<'\n';
}
else if(op==3){
cin>>x>>z;
update(1,1,n,dfn[x],dfn[x]+siz[x]-1,z);
}
else{
cin>>x;
cout<<query(1,1,n,dfn[x],dfn[x]+siz[x]-1)<<'\n';
}
}
return 0;
}