抱歉,先贴份代码,注释几天后再写。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#define mes(a,b) memset(a,b,sizeof(a))
#define N 100010
#define M 100010*2
#define ll long long
using namespace std;
ll son[N],siz[N],id[N],cnt,top[N],w[N],wt[N],dep[N],fa[N];
ll f[N],ne[M],to[M],tot;
ll root,n,m,p;
struct poi{
ll l,r,sum,bj;
}z[N*4];
void ad(ll x,ll y){
tot++;
ne[tot]=f[x];
f[x]=tot;
to[tot]=y;
}
void dfs1(ll wz,ll father,ll deep){
dep[wz]=deep;
fa[wz]=father;
ll maxx=0,sonxx=0;
ll y;
siz[wz]=1;
for(ll i=f[wz];i!=-1;i=ne[i]){
y=to[i];
if(y==father)continue;
dfs1(y,wz,deep+1);
siz[wz]+=siz[y];
if(siz[y]>maxx){
maxx=siz[y];
sonxx=y;
}
}
son[wz]=sonxx;
}
void dfs2(ll x,ll topf){
id[x]=++cnt;
wt[cnt]=w[x];
top[x]=topf;
if(!son[x])return;
dfs2(son[x],topf);
ll y;
for(ll i=f[x];i!=-1;i=ne[i]){
y=to[i];
if(y==fa[x] || y==son[x])continue;
dfs2(y,y);
}
}
void build(ll wz,ll l,ll r){
z[wz].l=l,z[wz].r=r,z[wz].bj=0;
if(l==r){
z[wz].sum=wt[l];
return;
}
ll mid;
mid=(l+r)>>1;
build(wz*2,l,mid);
build(wz*2+1,mid+1,r);
z[wz].sum=(z[wz*2].sum+z[wz*2+1].sum)%p;
}
void down(ll x){
z[x*2].sum+=(z[x*2].r-z[x*2].l+1)*z[x].bj;
z[x*2].sum%=p;
z[x*2].bj+=z[x].bj;
z[x*2].bj%=p;
z[x*2+1].sum+=(z[x*2+1].r-z[x*2+1].l+1)*z[x].bj;
z[x*2+1].sum%=p;
z[x*2+1].bj+=z[x].bj;
z[x*2+1].bj%=p;
z[x].bj=0;
}
void add(ll wz,ll l,ll r,ll x){
z[wz].sum+=(r-l+1)*x;
z[wz].sum%=p;
if(l==z[wz].l && r==z[wz].r){
z[wz].bj+=x;
z[wz].bj%=p;
return;
}
down(wz);
ll mid;
mid=(z[wz].l+z[wz].r)>>1;
if(r<=mid)add(wz*2,l,r,x);
else if(l>mid)add(wz*2+1,l,r,x);
else add(wz*2,l,mid,x),add(wz*2+1,mid+1,r,x);
}
ll cou(ll wz,ll l,ll r){
if(l==z[wz].l && r==z[wz].r){
return z[wz].sum%p;
}
down(wz);
ll mid;
mid=(z[wz].l+z[wz].r)>>1;
if(r<=mid)return cou(wz*2,l,r);
else if(l>mid)return cou(wz*2+1,l,r);
else return (cou(wz*2,l,mid)+cou(wz*2+1,mid+1,r))%p;
}
void cc1(ll x,ll y,ll z){
z=z%p;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
add(1,id[top[x]],id[x],z);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
add(1,id[y],id[x],z);
}
void cc2(ll x,ll y){
ll ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=cou(1,id[top[x]],id[x]);
ans%=p;
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans+=cou(1,id[y],id[x]);
ans%=p;
printf("%lld\n",ans);
}
void cc3(ll x,ll z){
z=z%p;
add(1,id[x],id[x]+siz[x]-1,z);
}
void cc4(ll x){
ll ans=0;
ans=cou(1,id[x],id[x]+siz[x]-1);
printf("%lld\n",ans);
}
int main(){
mes(f,-1);
scanf("%lld%lld%lld%lld",&n,&m,&root,&p);
for(ll i=1;i<=n;i++){
scanf("%lld",&w[i]);
w[i]%=p;
}
ll x,y;
for(ll i=1;i<n;i++){
scanf("%lld%lld",&x,&y);
ad(x,y);
ad(y,x);
}
dfs1(root,0,1);
dfs2(root,root);
build(1,1,n);
ll op,z;
while(m--){
scanf("%lld",&op);
switch(op){
case 1:{
scanf("%lld%lld%lld",&x,&y,&z);
cc1(x,y,z);
break;
}
case 2:{
scanf("%lld%lld",&x,&y);
cc2(x,y);
break;
}
case 3:{
scanf("%lld%lld",&x,&z);
cc3(x,z);
break;
}
case 4:{
scanf("%lld",&x);
cc4(x);
break;
}
}
}
return 0;
}