样例过了,交上去10分(AC #4)
#include<bits/stdc++.h>
#define ll long long
#define YJL_DRC_LCH_WJY_WQY_ZZH using
#define AK namespace
#define IOI std
#define Edge(x) for(int I=head[x];I;I=nxt[I])
YJL_DRC_LCH_WJY_WQY_ZZH AK IOI;
const int N=100005;
int n,m,root,u,v,op,x,y;
ll MOD,a[N],qz[N],z;
int head[N],to[N<<1],nxt[N<<1],tot;
void add(int Fr,int To){to[++tot]=To,nxt[tot]=head[Fr],head[Fr]=tot;}
int fa[N],top[N],dfn[N],siz[N],dep[N],son[N],Dfn;
struct SGT
{
#define lid id<<1
#define rid (lid)|1
struct tree
{
int l,r;
ll sum,lz;
}tr[N<<2];
void pu(int id)
{
tr[id].sum=(tr[lid].sum+tr[rid].sum)%MOD;
}
void pd(int id)
{
tree &now=tr[id];
ll &lz=now.lz;
if(!lz)return;
now.sum=(now.sum+now.lz*(now.r-now.l+1))%MOD;
tr[lid].lz+=lz,tr[rid].lz+=lz;
tr[lid].lz%=MOD,tr[rid].lz%=MOD;
lz=0;
}
void build(int l,int r,int id)
{
tr[id].l=l,tr[id].r=r,tr[id].lz=0;
if(l==r)return tr[id].sum=qz[l],void();
int mid=l+r>>1;
build(l,mid,lid);
build(mid+1,r,rid);
pu(id);
}
void mdf(int l,int r,int id)
{
if(tr[id].l==l&&tr[id].r==r)
return tr[id].lz=(tr[id].lz+z)%MOD,void();
pd(id);
if(tr[lid].r>=l)
if(tr[rid].l<=r)
mdf(l,tr[lid].r,lid),mdf(tr[rid].l,r,rid);
else mdf(l,r,lid);
else mdf(l,r,rid);
}
ll query(int l,int r,int id)
{
tree &now=tr[id];
if(now.l==l&&now.r==r)return (now.sum+now.lz*(r-l+1))%MOD;
pd(id);
if(tr[lid].r>=l)
if(tr[rid].l<=r)
return (query(l,tr[lid].r,lid)+query(tr[rid].l,r,rid)\
)%MOD;
else return query(l,r,lid);
return query(l,r,rid);
}
}sgt;
void dfs1(int now,int Fa,int Dep)
{
fa[now]=Fa,dep[now]=Dep,siz[now]=1;
int masiz=0;
Edge(now)
{
int t=to[I];
if(t!=Fa)
{
dfs1(t,now,Dep+1);
if(siz[t]>masiz)masiz=siz[t],son[now]=t;
siz[now]+=siz[t];
}
}
}
void dfs2(int now,int Top)
{
top[now]=Top,dfn[now]=++Dfn,qz[Dfn]=a[now];
if(!son[now])return;
dfs2(son[now],Top);
Edge(now)
{
int t=to[I];
if(t!=fa[now]&&t!=son[now])dfs2(t,t);
}
}
void Lmdf()//link add
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
sgt.mdf(dfn[top[x]],dfn[x],1);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
sgt.mdf(dfn[y],dfn[x],1);
}
ll Lquery()//link query
{
ll ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=(ans+sgt.query(dfn[top[x]],dfn[x],1))%MOD;
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ans=(ans+sgt.query(dfn[y],dfn[x],1))%MOD;
return ans;
}
void Tmdf()//tree add
{
sgt.mdf(dfn[x],dfn[x]+siz[x]-1,1);
}
ll Tquery()//tree query
{
return sgt.query(dfn[x],dfn[x]+siz[x]-1,1);
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m>>root>>MOD;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++)
{
cin>>u>>v;
add(u,v),add(v,u);
}
dfs1(root,0,1);
dfs2(root,root);
sgt.build(1,n,1);
while(m--)
{
cin>>op;
switch(op)
{
case 1:cin>>x>>y>>z;Lmdf();break;
case 2:cin>>x>>y;cout<<Lquery()<<endl;break;
case 3:cin>>x>>z;Tmdf();break;
case 4:cin>>x;cout<<Tquery()<<endl;
}
}
return 0;
}