题目传送门:这个
#include<iostream>
#include<vector>
#define len(x) (tree[x].r-tree[x].l+1)
using namespace std;
const int N=5e5+5;
struct node{
long long to,next;
}tu[2*N];
struct nodde{
long long l,r,sum,lazy;
}tree[N<<2];
long long n,m,cnt=1,tot,head[N],a[N],dis[N],sz[N],w[N],mod,rb[N],fa[N],depth[N],maxson[N],id[N],top[N];
void add(long long x,long long y){
tu[++tot].to=y;
tu[tot].next=head[x];
head[x]=tot;
}
void pushup(long long root){
tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
}
void pushdown(long long root){
if(tree[root].lazy){
tree[root<<1].sum+=len(root<<1)*tree[root].lazy;
tree[root<<1].lazy+=tree[root].lazy;
tree[root<<1|1].sum+=len(root<<1|1)*tree[root].lazy;
tree[root<<1|1].lazy+=tree[root].lazy;
tree[root].lazy=0;
}
}
void build(long long root,long long l,long long r){
tree[root].l=l;
tree[root].r=r;
if(l==r){
tree[root].sum=a[w[l]];
return ;
}
long long mid=(l+r)>>1;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
pushup(root);
}
void update(long long root,long long l,long long r,long long x,long long y,long long val){
if(x<=l&&y>=r){
tree[root].sum+=len(root)*val;
tree[root].lazy=val;
return ;
}
pushdown(root);
long long mid=(l+r)>>1;
if(x<mid) update(root<<1,l,mid,x,y,val);
if(y>=mid+1) update(root<<1|1,mid+1,r,x,y,val);
pushup(root);
}
long long query(long long root,long long l,long long r,long long x,long long y){
if(x<=l&&y>=r) return tree[root].sum;
pushdown(root);
long long mid=l+r>>1;
if(y<=mid) return query(root<<1,l,mid,x,y);
if(x>=mid+1) return query(root<<1|1,mid+1,r,x,y);
return query(root<<1,l,mid,x,y)+query(root<<1|1,mid+1,r,x,y);
}
void ddff(long long u,long long f){
fa[u]=f,sz[u]=1,depth[u]=depth[f]+1;
for(long long i=head[u];i;i=tu[i].next){
long long v=tu[i].to;
if(v==f) continue;
ddff(v,u);
sz[u]+=sz[v];
if(!maxson[u]||sz[maxson[u]]<sz[v]) maxson[u]=v;
}
}
void ddfff(long long u,long long bg){
top[u]=bg,id[u]=++tot;
w[tot]=u;
if(!maxson[u]){
rb[u]=tot;
return;
}
ddfff(maxson[u],bg);
for(long long i=head[u];i;i=tu[i].next){
long long v=tu[i].to;
if(v==fa[u]||v==maxson[u]) continue;
ddfff(v,v);
}
rb[u]=tot;
}
void update_chain(long long x,long long y,long long val){
while(top[x]!=top[y]){
if(depth[top[x]]<depth[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x],val);
x=fa[top[x]];
}
if(depth[x]<depth[y]) swap(x,y);
update(1,1,n,id[top[x]],id[x],val);
}
long long query_chain(long long x,long long y){
long long ans=0;
while(top[x]!=top[y]){
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans+=query(1,1,n,id[top[x]],id[x]);
ans%=mod;
x=fa[top[x]];
}
if(depth[x]<depth[y]) swap(x,y);
ans+=query(1,1,n,id[y],id[x]);
return ans%mod;
}
int main(){
long long root;
cin>>n>>m>>root>>mod;
for(long long i=1;i<=n;i++) cin>>a[i];
for(long long i=1;i<n;i++){
long long u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
ddff(root,0);
ddfff(root,root);
build(1,1,n);
while(m--){
long long op,x,y,z;
cin>>op;
if(op==1){
cin>>x>>y>>z;
update_chain(x,y,z);
}
else if(op==2){
cin>>x>>y;
cout<<query_chain(x,y);
}
else if(op==3){
cin>>x>>z;
update(1,1,n,id[x],rb[x],z);
}
else{
cin>>x;
cout<<query(1,1,n,id[x],rb[x]);
}
}
return 0;
}