#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,r;
int a,b;
long long mod;
long long tree[800400];
long long val[800200];
long long tag[800200];
int head[800200];
int to[800200];
int next[800200];
int fa[800200];
int size[800200];
int dep[800200];
int son[800200];
int num[800200];
int dfn[800200];
int top[800200];
int tot=0,cnt=0,type;
int kx,ky;
long long kz;
long long ans=0;
inline long long read()
{
char ch=getchar();
long long num1=0;
while(!(ch>='0'&&ch<='9'))
ch=getchar();
while(ch>='0'&&ch<='9')
{
num1=num1*10+ch-'0';
ch=getchar();
}
return num1;
}
void xx(int u,int v)
{
to[cnt]=v;
next[cnt]=head[u];
head[u]=cnt;
cnt++;
}
void dfs1(int x,int father)
{
dep[x]=dep[father]+1;
size[x]=1;
for(int i=head[x];i!=-1;i=next[i])
{
int y=to[i];
if(y==father)
continue;
dfs1(y,x);
fa[y]=x;
size[x]+=size[y];
if(size[y]>size[son[x]])
son[x]=y;
}
}
void dfs2(int x,int father)
{
tot++;
dfn[tot]=x;
num[x]=tot;
top[x]=father;
if(son[x]!=0)
dfs2(son[x],father);
for(int i=head[x];i!=-1;i=next[i])
{
int y=to[i];
if(y==fa[x]||y==son[x])
continue;
dfs2(y,y);
}
}
void pushup(int k)
{
tree[k*2]=(tree[k*2]+tag[k])%mod;
tree[k*2+1]=(tree[k*2+1]+tag[k])%mod;
tag[k*2]=(tag[k*2]+tag[k]);
tag[k*2+1]=(tag[k*2+1]+tag[k]);
tag[k]=0;
}
void build(int l,int r,int k)
{
if(l==r)
{
tree[k]=val[dfn[l]]%mod;
return;
}
int mid=(l+r)/2;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
tree[k]=(tree[k*2]+tree[k*2+1])%mod;
}
void change(int l,int r,int l1,int r1,int k,int x)
{
if(l<=l1&&r1<=r)
{
tree[k]+=x;
tag[k]+=x;
return;
}
if(tag[k])
pushup(k);
int mid=(l1+r1)/2;
if(l>mid)
change(l,r,mid+1,r1,k*2+1,x);
else if(r<=mid)
change(l,r,l1,mid,k*2,x);
else
{
change(l,mid,l1,mid,k*2,x);
change(mid+1,r,mid+1,r1,k*2+1,x);
}
tree[k]=(tree[k*2]+tree[k*2+1])%mod;
}
long long query(int L,int R,int l,int r,int k)
{
if(L<=l&&r<=R)
return tree[k];
int mid=(l+r)/2;
if(tag[k])
pushup(k);
if(L>mid)
return query(L,R,mid+1,r,k*2+1);
else if(R<=mid)
return query(L,R,l,mid,k*2);
else
return (query(L,mid,l,mid,k*2)+query(mid+1,R,mid+1,r,k*2+1))%mod;
}
void lca(int x,int y,int z,int o)
{
ans=0;
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[top[x]]>=dep[top[y]])
{
if(o==0)
change(num[x],num[top[x]],1,n,1,z);
else
ans=(ans+query(num[x],num[top[x]],1,n,1))%mod;
x=fa[fx],fx=top[x];
}
else
{
if(o==0)
change(num[y],num[top[y]],1,n,1,z);
else
ans=(ans+query(num[y],num[top[y]],1,n,1));
y=fa[fy],fy=top[y];
}
}
// printf("%d %d\n",num[10458],num[55578]);
if(num[x]>num[y])
if(o==0)
change(num[y],num[x],1,n,1,z);
else
ans=(ans+query(num[y],num[x],1,n,1))%mod;
else
if(o==0)
change(num[x],num[y],1,n,1,z);
else
ans=(ans+query(num[x],num[y],1,n,1))%mod;
return;
}
int main()
{
n=read(),m=read(),r=read(),mod=read();
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
val[i]=read();
for(int i=1;i<n;i++)
{
a=read(),b=read();
xx(a,b),xx(b,a);
}
dfs1(r,0);
dfs2(r,r);
build(1,n,1);
// printf("%d %d\n",num[10458],num[55578]);
while(m--)
{
type=read();
if(type==1)
{
kx=read(),ky=read(),kz=read();
lca(kx,ky,kz,0);
}
else if(type==2)
{
ans=0;
kx=read(),ky=read();
lca(kx,ky,0,1);
printf("%lld\n",ans%mod);
}
else if(type==3)
{
kx=read(),kz=read();
change(num[kx],num[kx]+size[kx]-1,1,n,1,kz);
}
else if(type==4)
{
kx=read();
printf("%lld\n",query(num[kx],num[kx]+size[kx]-1,1,n,1)%mod);
}
}
}
一个点WA,其他RE
经确认,系num数组不知为何被清为0(预处理没有问题)
恳求大佬们帮帮蒟蒻(找错找了1个多小时了QAQ)