rt,我的代码如下:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
struct edge{LL v,next;}e[1000005];
struct tree{LL l,r,w,tag;}tree[4000005];
LL n,m,i,u,v,x,y,z,opt,cnt,root,p,a[500005],d[500005],id[500005],fa[500005],son[500005],seg[500005],top[500005],size[500005],head[500005];
inline LL read(){
LL x=0,y=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar()) y-=(c=='-')<<1;
for(;c>='0'&&c<='9';c=getchar()) x=x*10+(c&15);
return x*y;
}
void add(LL u,LL v){
e[++cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt;
}
void dfs1(LL u,LL f){
fa[u]=f;d[u]=d[f]+1;size[u]=1;
for(LL i=head[u];i;i=e[i].next){
LL v=e[i].v;
if(v==f) return;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
void dfs2(LL u,LL f){
top[u]=f;id[u]=++id[0];seg[id[0]]=u;
if(!son[u]) return;dfs2(son[u],f);
for(LL i=head[u];i;i=e[i].next){
LL v=e[i].v;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
void build(LL k,LL l,LL r){
tree[k].l=l;tree[k].r=r;
if(l==r){tree[k].w=a[seg[l]]%p;return;}
LL mid=l+r>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
tree[k].w=(tree[k<<1].w+tree[k<<1|1].w)%p;
}
void down(LL k){
LL son=k<<1;
tree[son].tag=(tree[son].tag+tree[k].tag)%p;
tree[son|1].tag=(tree[son|1].tag+tree[k].tag)%p;
tree[son].w=(tree[son].w+(tree[son].r-tree[son].l+1)*tree[k].tag)%p;
tree[son|1].w=(tree[son|1].w+(tree[son|1].r-tree[son|1].l+1)*tree[k].tag)%p;
tree[k].tag=0;
}
void modify(LL k,LL x,LL y,LL z){
if(x<=tree[k].l&&y>=tree[k].r){
tree[k].w=(tree[k].w+(tree[k].r-tree[k].l+1)*z)%p;
tree[k].tag=(tree[k].tag+z)%p;
return;
}
if(tree[k].tag) down(k);
LL mid=tree[k].l+tree[k].r>>1;
if(x<=mid) modify(k<<1,x,y,z);
if(y>mid) modify(k<<1|1,x,y,z);
tree[k].w=(tree[k<<1].w+tree[k<<1|1].w)%p;
}
LL query(LL k,LL x,LL y){
if(x<=tree[k].l&&y>=tree[k].r) return tree[k].w;
if(tree[k].tag) down(k);
LL mid=tree[k].l+tree[k].r>>1,res=0;
if(x<=mid) res=(res+query(k<<1,x,y))%p;
if(y>mid) res=(res+query(k<<1|1,x,y))%p;
return res;
}
LL change(LL x,LL y,LL z){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
modify(1,id[top[x]],id[x],z);
x=fa[top[x]];
}
if(d[x]>d[y]) swap(x,y);modify(1,id[x],id[y],z);
}
LL ask(LL x,LL y){
LL res=0;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
res=(res+query(1,id[top[x]],id[x]))%p;
x=fa[top[x]];
}
if(d[x]>d[y]) swap(x,y);return (res+query(1,id[x],id[y]))%p;
}
int main(){
//freopen("P3384_2.in","r",stdin);
//freopen("P3384_2.out","w",stdout);
n=read();m=read();root=read();p=read();
for(i=1;i<=n;i++) a[i]=read();
for(i=1;i<n;i++) u=read(),v=read(),add(u,v),add(v,u);
dfs1(root,0);dfs2(root,root);build(1,1,id[0]);
while(m--){
opt=read();
if(opt==1) x=read(),y=read(),z=read(),change(x,y,z%p);
if(opt==2) x=read(),y=read(),printf("%lld\n",ask(x,y));
if(opt==3) x=read(),z=read(),modify(1,id[x],id[x]+size[x]-1,z%p);
if(opt==4) x=read(),printf("%lld\n",query(1,id[x],id[x]+size[x]-1));
}
}