RT,样例输出 2,7。
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
struct edge{
int to,next;
} e[MAXN<<1];
int head[MAXN],cnt;
inline void add(int u,int v)
{
e[++cnt].to=v; e[cnt].next=head[u]; head[u]=cnt;
}
//树剖
int top[MAXN],siz[MAXN],fa[MAXN],depth[MAXN],son[MAXN],id[MAXN],a[MAXN],w[MAXN],idx;
void dfs1(int u,int fath,int dep)
{
fa[u]=fath; depth[u]=dep; siz[u]=1;
int maxson=-1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fath) continue;
dfs1(v,u,dep+1);
siz[u]+=siz[v];
if(siz[v]>maxson){maxson=siz[v]; son[u]=v;}
}
}
void dfs2(int u,int tp)
{
id[u]=++idx; top[u]=tp; w[cnt]=a[u];
if(!son[u]) return;
dfs2(son[u],tp);
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
//线段树
int n,m,rt,mod;
int tree[MAXN<<2],tag[MAXN<<2];
inline void push_up(int p){ tree[p]=(tree[p<<1]+tree[p<<1|1])%mod;}
void build(int p,int l,int r)
{
if(l==r){ tree[p]=w[l];return;}
int mid=(l+r)>>1;
build(p<<1,l,mid); build(p<<1|1,mid+1,r);
push_up(p);
}
inline void push_down(int p,int l,int r)
{
if(tag[p])
{
int mid=(l+r)>>1;
tag[p<<1]=(tag[p<<1]+tag[p])%mod;
tag[p<<1|1]=(tag[p<<1|1]+tag[p])%mod;
tree[p<<1]=(tree[p<<1]+(mid-l+1)*tag[p])%mod;
tree[p<<1|1]=(tree[p<<1|1]+(r-mid)*tag[p])%mod;
tag[p]=0;
}
}
void update(int p,int l,int r,int L,int R,int k)
{
if(L<=l&&r<=R){tree[p]=(tree[p]+k*(r-l+1))%mod; tag[p]=(tag[p]+k)%mod; return;};
push_down(p,l,r);
int mid=(l+r)>>1;
if(L<=mid) update(p<<1,l,mid,L,R,k);
if(mid<R) update(p<<1|1,mid+1,r,L,R,k);
push_up(p);
}
int query(int p,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return tree[p];
push_down(p,l,r);
int mid=(l+r)>>1,res=0;
if(L<=mid) res=(res+query(p<<1,l,mid,L,R))%mod;
if(mid<R) res=(res+query(p<<1|1,mid+1,r,L,R))%mod;
return res;
}
//树剖操作
inline int range_query(int u,int v)
{
int res=0;
while(top[u]^top[v])
{
if(depth[top[u]]<depth[top[v]]) swap(u,v);
res=(res+query(1,1,n,id[top[u]],id[u]));
u=fa[top[u]];
}
if(depth[u]>depth[v]) swap(u,v);
res=(res+query(1,1,n,id[u],id[v]))%mod;
return res;
}
inline int query_son(int u){return query(1,1,n,id[u],id[u]+siz[u]-1);}
inline void range_update(int u,int v,int k)
{
k%=mod;
while(top[u]^top[v])
{
if(depth[top[u]]<depth[top[v]]) swap(u,v);
update(1,1,n,id[top[u]],id[u],k);
u=fa[top[u]];
}
if(depth[u]>depth[v]) swap(u,v);
update(1,1,n,id[u],id[v],k);
}
inline void update_son(int u,int k){update(1,1,n,id[u],id[u]+siz[u]-1,k);}
inline int read()
{
int x=0,f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=(x<<1)+(x<<3)+c-48;
return x*f;
}
int main()
{
n=read(); m=read(); rt=read(); mod=read();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<n;i++)
{
int u=read(),v=read();
add(u,v); add(v,u);
}
dfs1(rt,0,1);
dfs2(rt,rt);
build(1,1,n);
while(m--)
{
int opt=read(),x,y,k;
switch(opt)
{
case 1:
x=read(); y=read(); k=read();
range_update(x,y,k);
break;
case 2:
x=read(); y=read();
printf("%d\n",range_query(x,y));
break;
case 3:
x=read(); y=read();
update_son(x,y);
break;
case 4:
x=read();
printf("%d\n",query_son(x));
break;
}
}
return 0;
}