1,3,4点过了
#include<iostream>
#include<array>
#include<algorithm>
#include<vector>
#include<bitset>
using namespace std;
using gg=unsigned long long;
array<gg,500010> v;
array<gg,500010> son,fa,dep,siz;
array<gg,500010> top,dfn,rnk;
array<gg,2000010> tree,flag1;
array<vector<gg>,500010> tp;
bitset<500010> flag;
gg cnt=0,n,m,r,mod,x,y,z;
void update_need(gg l,gg r,gg k,gg nl,gg nr,gg p)
{
if(l<=nl&&nr<=r)
{
tree[p]+=(nr-nl+1)*k;
tree[p]%=mod;
flag1[p]+=k;
return;
}
gg mid=(nl+nr)/2;
if(flag1[p]&&nr!=nl)
{
tree[p*2]+=flag1[p]*(mid-nl+1);
tree[p*2]%=mod;
tree[p*2+1]+=flag1[p]*(nr-mid);
tree[p*2+1]%=mod;
flag1[p*2]+=flag1[p];
flag1[p*2+1]+=flag1[p];
flag1[p]=0;
}
if(l<=mid)
{
update_need(l,r,k,nl,mid,p*2);
}
if(r>mid)
{
update_need(l,r,k,mid+1,nr,p*2+1);
}
tree[p]=(tree[p*2]+tree[p*2+1])%mod;
return;
}
void build1(const gg &p)
{
gg tpcnt=cnt;
cnt++;
dep[p]=dep[fa[p]]+1;
flag[p]=true;
for(gg i=0;i<tp[p].size();i++)
{
if(!flag[tp[p][i]])
{
fa[tp[p][i]]=p;
build1(tp[p][i]);
}
}
siz[p]=cnt-tpcnt;
for(gg i=0;i<tp[p].size();i++)
{
if(siz[son[p]]<siz[tp[p][i]]&&fa[tp[p][i]]==p)
{
son[p]=tp[p][i];
}
}
return;
}
void build2(const gg &p,const gg &v)
{
cnt++;
top[p]=v;
dfn[p]=cnt;
rnk[cnt]=p;
if(!son[p])
{
return;
}
build2(son[p],v);
for(gg i=0;i<tp[p].size();i++)
{
if(tp[p][i]!=son[p]&&fa[tp[p][i]]==p)
{
build2(tp[p][i],tp[p][i]);
}
}
return;
}
void build3(const gg &l,const gg &r,const gg &p)
{
if(l==r)
{
tree[p]=v[rnk[l]];
if(tree[p]>mod)
{
tree[p]%=mod;
}
return;
}
gg mid=(l+r)/2;
build3(l,mid,2*p);
build3(mid+1,r,2*p+1);
tree[p]=(tree[2*p]+tree[2*p+1])%mod;
return;
}
gg checksum(const gg &l,const gg &r,const gg &ll,const gg &rr,const gg &p)
{
if(l>=ll&&r<=rr)
{
return tree[p];
}
gg mid=(l+r)/2,tpsum=0;
if(flag1[p])
{
tree[p*2]+=flag1[p]*(mid-ll+1);
tree[p*2]%=mod;
tree[p*2+1]+=flag1[p]*(rr-mid);
tree[p*2+1]%=mod;
flag1[p*2]+=flag1[p];
flag1[p*2+1]+=flag1[p];
flag1[p]=0;
}
if(ll<=mid)
{
tpsum+=checksum(l,mid,ll,rr,2*p);
tpsum%=mod;
}
if(rr>=mid+1)
{
tpsum+=checksum(mid+1,r,ll,rr,2*p+1);
tpsum%=mod;
}
return tpsum;
}
gg checkson(const gg &x)
{
return checksum(1,n,dfn[x],dfn[x]+siz[x]-1,1);
}
gg checklcasum(gg x,gg y)
{
gg sumtp=0;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
sumtp+=checksum(1,n,dfn[top[x]],dfn[x],1);
sumtp%=mod;
x=fa[top[x]];
}
else
{
sumtp+=checksum(1,n,dfn[top[y]],dfn[y],1);
sumtp%=mod;
y=fa[top[y]];
}
}
if(dep[x]>dep[y])
{
sumtp+=checksum(1,n,dfn[y],dfn[x],1);
sumtp%=mod;
}
else
{
sumtp+=checksum(1,n,dfn[x],dfn[y],1);
sumtp%=mod;
}
return sumtp;
}
void chson(const gg &x,const gg &z)
{
update_need(dfn[x],dfn[x]+siz[x]-1,z,1,n,1);
return;
}
void chlca(gg x,gg y,gg z)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
{
update_need(dfn[top[x]],dfn[x],z,1,n,1);
x=fa[top[x]];
}
else
{
update_need(dfn[top[y]],dfn[y],z,1,n,1);
y=fa[top[y]];
}
}
if(dep[x]>dep[y])
{
update_need(dfn[y],dfn[x],z,1,n,1);
}
else
{
update_need(dfn[x],dfn[y],z,1,n,1);
}
return;
}
int main()
{
cin>>n>>m>>r>>mod;
for(gg i=1;i<=n;i++)
{
cin>>v[i];
}
for(gg i=1;i<=n-1;i++)
{
cin>>x>>y;
tp[x].push_back(y);
tp[y].push_back(x);
}
build1(r);
cnt=0;
build2(r,r);
build3(1,n,1);
for(gg i=1;i<=m;i++)
{
cin>>x;
switch(x)
{
case 1:{
cin>>x>>y>>z;
chlca(x,y,z);
break;
}
case 2:{
cin>>x>>y;
cout<<checklcasum(x,y)%mod<<'\n';
break;
}
case 3:{
cin>>x>>z;
chson(x,z);
break;
}
case 4:{
cin>>x;
cout<<checkson(x)%mod<<'\n';
break;
}
}
}
return 0;
}