不知道哪错了
#include <bits/stdc++.h>
using namespace std;
#define reg register
#define len(x) (node[x].r-node[x].l+1)
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int maxn=1e5+5;
int n,m,rt,p;
//----------make_graph------------
struct EDGE
{
int to,nxt;
}edge[maxn<<1];
int nxt[maxn<<1];
int head[maxn<<1];
int tot;
inline void add(int u,int to)
{
edge[++tot].to=to;
edge[tot].nxt=head[u];
head[u]=tot;
}
//-------------tree---------
struct Node
{
int val,lazy,l,r,ls,rs;
}node[maxn];
int val[maxn];//题目给定点权
int dfn[maxn];//当前节点的dfs序
int hs[maxn];//当前节点的重儿子
int noderank[maxn];//第i个访问到的节点是谁
int nodesize[maxn];//当前节点为根的子树的大小
int dep[maxn];//当前节点深度
int top[maxn];//当前节点的链顶
int cnt;
int father[maxn];
void dfs1(int x)
{
cout<<"x: "<<x<<endl;
nodesize[x]=1;
dep[x]=dep[father[x]]+1;
for(int i=head[x];i;i=edge[i].nxt)
{
reg int to=edge[i].to;
if(to==father[x])continue;
father[to]=x;
dfs1(to);
nodesize[x]+=nodesize[to];
if(nodesize[to]>=nodesize[hs[x]])
{
hs[x]=to;
}
}
}
void dfs2(int x,int tp)
{
cout<<"x: "<<x<<endl;
dfn[x]=++cnt;
noderank[cnt]=x;
top[x]=tp;
if(hs[x])
dfs2(hs[x],tp);
for(int i=head[x];i;i=edge[i].nxt)
{
reg int to=edge[i].to;
if(to==hs[x]||to==father[x])continue;
dfs2(to,to);
}
}
inline void push_up(int x)
{
node[x].val=(node[node[x].ls].val+node[node[x].rs].val)%p;
}
void Build(int x,int l,int r)
{
if(l==r)
{
node[x].val=val[noderank[l]]%p;
node[x].l=node[x].r=l;
return;
}
node[x].ls=++cnt;
node[x].rs=++cnt;
int mid=(l+r)>>1;
Build(node[x].ls,l,mid);
Build(node[x].rs,mid+1,r);
push_up(x);
}
inline void pushdown(int x)
{
if(!node[x].lazy)return;
node[node[x].ls].lazy+=node[x].lazy;
node[node[x].rs].lazy+=node[x].lazy;
node[node[x].ls].lazy%=p;
node[node[x].rs].lazy%=p;
node[node[x].ls].val+=(len(node[x].ls)*(node[node[x].ls].lazy));
node[node[x].rs].val+=(len(node[x].rs)*(node[node[x].rs].lazy));
node[node[x].ls].val%=p;
node[node[x].rs].val%=p;
node[x].lazy=0;
}
void update(int x,int l,int r,int c)
{//对线段树某一区间修改
if(node[x].l>=l&&node[x].r<=r)
{
node[x].lazy+=c;
return;
}
pushdown(x);
int mid=(node[x].l+node[x].r)>>1;
if(mid>=l)update(node[x].ls,l,r,c);
if(mid<r)update(node[x].rs,l,r,c);
push_up(x);
}
int query(int x,int l,int r)
{//对线段树某一区间修改
if(node[x].l>=l&&node[x].r<=r)
{
return node[x].val%p;
}
pushdown(x);
int ans=0;
//cout<<"l: "<<l<<" r: "<<r<<endl;
int mid=(node[x].l+node[x].r)>>1;
if(mid>=l)ans+=query(node[x].ls,l,r);
if(mid<r)ans+=query(node[x].rs,l,r);
return ans%p;
}
int get_sum(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[x]<dep[y])swap(x,y);
ans+=query(1,dfn[top[x]],dfn[x])%p;
x=father[top[x]];
}
if(dfn[x]>dfn[y])swap(x,y);
ans+=query(1,dfn[x],dfn[y])%p;
return ans%p;
}
void updates(int x,int y,int z)
{
while(top[x]!=top[y])
{
if(dep[x]<dep[y])swap(x,y);
update(1,dfn[top[x]],dfn[x],z);
x=father[top[x]];
}
if(dfn[x]>dfn[y])swap(x,y);
update(1,dfn[x],dfn[y],z);
}
//--------------main-------
int main()
{
n=read();
m=read();
rt=read();
p=read();
for(reg int i=1;i<=n;i++)val[i]=read();
reg int x,y;
for(reg int i=1;i<n;i++)
{
x=read();
y=read();
add(x,y);
add(y,x);
}
dfs1(rt);
dfs2(rt,rt);
cnt=1;
Build(cnt,1,n);
int op,z;
for(reg int i=1;i<=m;i++)
{
op=read();
if(op==1)
{
x=read();
y=read();
z=read();
updates(x,y,z);
}
if(op==2)
{
x=read();
y=read();
printf("%d\n",get_sum(x,y));
}
if(op==3)
{
x=read();
z=read();
update(1,dfn[x],dfn[x]+nodesize[x]-1,z);
}
if(op==4)
{
x=read();
printf("%d\n",query(1,dfn[x],dfn[x]+nodesize[x]-1));
}
}
#ifndef ONLINE_JUDGE
system("pause");
#endif
return 0;
}