代码有一点长,大佬辛苦了
#include<bits/stdc++.h>
#define FOR(u) for(int i=G.head[u];i;i=G.nex[i])
#define lc (d<<1)
#define rc (d<<1|1)
#define ll long long
using namespace std;
struct my_edge {
int head[100005],nex[200005],to[200005],size;
void push(int u,int v) {
nex[++size]=head[u];
to[size]=v;
head[u]=size;
}
void clear() {
size=0;
memset(head,0,sizeof head);
}
} G;
struct node {
ll lb,sum;
} tree[400005];
ll read() {
ll x=0;
char y=getchar();
bool flag=0;
while(y<'0' || y>'9') {
if(y=='-')flag=1;
y=getchar();
}
while((y>='0' && y<='9')) {
x=x*10+(y-'0');
y=getchar();
}
if(flag)return -x;
return x;
}
void write(ll x) {
if(x<0) {
putchar('-');
x=-x;
}
if(x<10)putchar(x+'0');
else {
write(x/10);
putchar(x%10+'0');
}
}
int n,m,u,v,root,mod,data[100005],fa[100005],h[100005],son[100005],siz[100005];
int top[100005],id[100005],sum[100005],cnt;
int op,x,y,z;
void Up(int &d) {
tree[d].sum=(tree[lc].sum+tree[rc].sum)%mod;
}
void Down(int &d,int &l,int &r) {
if(tree[d].lb) {
int mid=l+r>>1;
tree[lc].sum+=tree[d].lb*(mid-l+1);
tree[rc].sum+=tree[d].lb*(r-mid);
tree[lc].sum%=mod;
tree[lc].sum%=mod;
tree[lc].lb+=tree[d].lb;
tree[rc].lb+=tree[d].lb;
tree[lc].lb%=mod;
tree[rc].lb%=mod;
tree[d].lb=0;
}
}
void dfs1(int u,int f) {
fa[u]=f;
h[u]=h[f]+1;
siz[u]=1;
int v,maxid=0;
FOR(u) {
v=G.to[i];
if(f==v)continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[maxid])maxid=v;
}
son[u]=maxid;
}
void dfs2(int u,int t) {
top[u]=t;
id[u]=++cnt;
sum[cnt]=data[u];
if(!son[u])return;
dfs2(son[u],t);
FOR(u) {
v=G.to[i];
if(v==fa[u] || v==son[u])continue;
dfs2(v,v);
}
}
void build(int d,int l,int r) {
tree[d]= {0,sum[r]};
if(l==r)return;
int mid=(l+r>>1);
build(lc,l,mid);
build(rc,mid+1,r);
Up(d);
}
void change(int d,int l,int r) {
if(r<x||y<l)return;
if(x<=l && r<=y) {
tree[d].lb+=z;
tree[d].sum+=z*(r-l+1);
return;
}
Down(d,l,r);
int mid=l+r>>1;
change(lc,l,mid),change(rc,mid+1,r);
Up(d);
}
void change_qj(int u,int v) {
while(top[u]!=top[v]) {
if(h[top[u]]<h[top[v]])swap(u,v);
change(1,id[top[u]],id[u]);
u=fa[top[u]];
}
if(h[u]<h[v])swap(u,v);
change(1,id[v],id[u]);
}
ll query(int d,int l,int r) {
if(r<x||y<l)return 0;
if(x<=l && r<=y)return tree[d].sum;
Down(d,l,r);
int mid=l+r>>1;
return (query(lc,l,mid)+query(rc,mid+1,r))%mod;
}
ll query_qj(int u,int v) {
ll sum=0;
while(top[u]!=top[v]) {
if(h[top[u]]<h[top[v]])swap(u,v);
sum+=query(1,id[top[u]],id[u]);
sum%=mod;
u=fa[top[u]];
}
if(h[u]<h[v])swap(u,v);
sum+=query(1,id[v],id[u]);
return sum%mod;
}
void change_tree(int u) {
change(1,id[u],id[u]+siz[u]-1);
}
ll query_tree(int u) {
return query(1,id[u],id[u]+siz[u]-1)%mod;
}
int main() {
n=read();
m=read();
root=read();
mod=read();
for(int i=1; i<=n; i++)data[i]=read();
for(int i=1; i<n; i++) {
u=read();
v=read();
G.push(u,v);
G.push(v,u);
}
dfs1(root,0);
dfs2(root,root);
build(1,1,n);
while(m--) {
op=read();
if(op==1) {
x=read();
y=read();
z=read();
change_qj(x,y);
} else if(op==2) {
x=read();
y=read();
cout<<query_qj(x,y)<<'\n';
} else if(op==3) {
x=read();
z=read();
change_tree(x);
} else {
x=read();
cout<<query_tree(x)<<'\n';
}
}
return 0;
}
%%%