一直找不出 bug 啊
请不要嫌弃蒟蒻的马蜂
#include<cstdio>
#include<vector>
#include<cstdlib>
#define int long long
using namespace std;
int n,m,root,MOD;
int tot;
int a[100001];
int w[100001];
int id[10001];
int sz[100001];
int fa[100001];
int top[100001];
int son[100001];
int dep[100001];
int Tag[100001<<2],c[100001<<2];
vector<int> G[100001];
void build(int o,int l,int r)
{
if(l==r)
{
c[o]=w[l];
c[o]%=MOD;
return;
}
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
c[o]=c[o<<1]+c[o<<1|1];
c[o]%=MOD;
}
void addTag(int o,int l,int r,int v)
{
Tag[o]+=v;
c[o]+=(r-l+1)*v;
c[o]%=MOD;
}
void downTag(int o,int l,int r,int mid)
{
if(Tag[o]==0)
{
return;
}
addTag(o<<1,l,mid,Tag[o]);
addTag(o<<1|1,mid+1,r,Tag[o]);
Tag[o]=0;
}
int query_tree(int o,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
return c[o];
}
if(l>y||r<x)
{
return 0;
}
int mid=(l+r)>>1;
downTag(o,l,r,mid);
int left=query_tree(o<<1,l,mid,x,y);
int right=query_tree(o<<1|1,mid+1,r,x,y);
return (left+right)%MOD;
}
void update_tree(int o,int l,int r,int x,int y,int v)
{
if(x<=l&&r<=y)
{
addTag(o,l,r,v);
return;
}
if(l>y||r<x)
{
return;
}
int mid=(l+r)>>1;
downTag(o,l,r,mid);
update_tree(o<<1,l,mid,x,y,v);
update_tree(o<<1|1,mid+1,r,x,y,v);
c[o]=c[o<<1]+c[o<<1|1];
c[o]%=MOD;
}
void Swap(int &x,int &y)
{
int temp=x;
x=y;
y=temp;
}
void dfs_first(int u,int father)
{
sz[u]=1;
fa[u]=father;
int max_son_sz=-1;
dep[u]=dep[father]+1;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==father)
{
continue;
}
dfs_first(v,u);
sz[u]+=sz[v];
if(sz[v]>max_son_sz)
{
son[u]=v;
max_son_sz=sz[v];
}
}
}
void dfs_second(int u,int top_of_u)
{
id[u]=++tot;
w[id[u]]=a[u];
top[u]=top_of_u;
if(son[u]==0)
{
return;
}
dfs_second(son[u],top_of_u);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==fa[u]||v==son[u])
{
continue;
}
dfs_second(v,v);
}
}
int query_son(int x)
{
return query_tree(1,1,n,id[x],id[x]+sz[x]-1)%MOD;
}
int query_road(int x,int y)
{
int res=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{
Swap(x,y);
}
res+=query_tree(1,1,n,id[top[x]],id[x]);
res%=MOD;
x=top[x];
x=fa[x];
}
if(dep[x]>dep[y])
{
Swap(x,y);
}
res+=query_tree(1,1,n,id[x],id[y]);
res%=MOD;
return res;
}
void update_son(int x,int v)
{
v%=MOD;
update_tree(1,1,n,id[x],id[x]+sz[x]-1,v);
}
void update_road(int x,int y,int v)
{
v%=MOD;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{
Swap(x,y);
}
update_tree(1,1,n,id[top[x]],id[x],v);
x=top[x];
x=fa[x];
}
if(dep[x]>dep[y])
{
Swap(x,y);
}
update_tree(1,1,n,id[x],id[y],v);
}
signed main()
{
scanf("%lld%lld%lld%lld",&n,&m,&root,&MOD);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%lld%lld",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs_first(root,0);
dfs_second(root,root);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int opt,x,y,v;
scanf("%lld",&opt);
if(opt==1)
{
scanf("%lld%lld%lld",&x,&y,&v);
update_road(x,y,v);
}
else if(opt==2)
{
scanf("%lld%lld",&x,&y);
printf("%lld\n",query_road(x,y));
}
else if(opt==3)
{
scanf("%lld%lld",&x,&v);
update_son(x,v);
}
else
{
scanf("%lld",&x);
printf("%lld\n",query_son(x));
}
}
return 0;
}