RT,90分,第十个点RE
dfs1里面有问题导致停止运行,但是查不出来
#include<bits/stdc++.h>
#define I long long
#define R register
#define il inline
#define INF 0x7fffffff
#define rt return
using namespace std;
const int N=1e5+7;
I n,m,root,HgS;
I e,st[N<<1],nxt[N<<1],to[N<<1],a[N],wt[N];//链式前向星数组
I cnt;
struct node{
I father,size,depth,son,sz;
I top,dfn;
#define fa(p) tree[p].father
#define sz(p) tree[p].sz
#define dep(p) tree[p].depth
#define son(p) tree[p].son
#define top(p) tree[p].top
#define dfn(p) tree[p].dfn
}tree[N];
struct Segment{
I lef,rig,len;
I tot,tag;
#define l(p) segment[p].lef
#define r(p) segment[p].rig
#define len(p) segment[p].len
#define tot(p) segment[p].tot
#define tag(p) segment[p].tag
}segment[N<<2];
il I d(){
I x=0,f=1;
char c=0;
while(!isdigit(c=getchar()))f-=(c=='-')*2;
while(isdigit(c)){x=(x<<1)+(x<<3)+f*(c-48);c=getchar();}
rt x;
}
il void add(I x,I y){
to[++e]=y;
nxt[e]=st[x];
st[x]=e;
}//链式前向星加边(双向)
il I ls(I k){return k<<1;}//左儿子
il I rs(I k){return k<<1|1;}//右儿子
il void build(I id,I l,I r){
len(id)=r-l+1;
tag(id)=0;
l(id)=l;
r(id)=r;
if(l==r){
tot(id)=wt[l]%HgS;
return;
}
I mid=l+r>>1;
build(ls(id),l,mid);
build(rs(id),mid+1,r);
tot(id)=(tot(ls(id))+tot(rs(id)))%HgS;
}
il void change_(I id,I val_plus){
tot(id)=(tot(id)+len(id)*val_plus%HgS)%HgS;
tag(id)=(tag(id)+val_plus)%HgS;
}
il void push_down(I id){
change_(ls(id),tag(id));
change_(rs(id),tag(id));
tag(id)=0;
}
il I query(I x,I y,I id){
// printf("%lld %lld %lld\n",x,y,id);
if(x<=l(id)&&r(id)<=y)return tot(id);
I sum=0,mid=l(id)+r(id)>>1;
if(tag(id))push_down(id);
if(x<=mid)sum=(sum+query(x,y,ls(id))%HgS)%HgS;
if(y>mid) sum=(sum+query(x,y,rs(id))%HgS)%HgS;
return sum;
}
il void update(I x,I y,I id,I k){
if(x<=l(id)&&r(id)<=y){
tot(id)=(tot(id)+k*len(id)%HgS)%HgS;
tag(id)=(tag(id)+k)%HgS;
return ;
}
if(tag(id))push_down(id);
I mid=l(id)+r(id)>>1;
if(x<=mid)update(x,y,ls(id),k);
if(y>mid) update(x,y,rs(id),k);
tot(id)=(tot(ls(id))+tot(rs(id)))%HgS;
}
il void dfs1(I x,I f,I deep){
I son_maxn=-1,k;
R I i;
dep(x)=deep;
fa(x)=f;
sz(x)=1;
for(i=st[x];i;i=nxt[i]){
k=to[i];
if(k==f)continue;
dfs1(k,x,deep+1);
sz(x)+=sz(k);
if(sz(k)>son_maxn){son(x)=k;son_maxn=sz(k);}
}
}
il void dfs2(I x,I Top){
I y;
R I i;
dfn(x)=++cnt;
wt[cnt]=a[x];
top(x)=Top;
if(!son(x)) return;
dfs2(son(x),Top);
for(i=st[x];i;i=nxt[i]){
y=to[i];
if(y==fa(x)||y==son(x)) continue;
dfs2(y,y);
}
}
il void update_road(I x,I y,I k){
//操作1 将树从x到y结点最短路径上所有节点的值都加上z
while(top(x)!=top(y)){
if(dep(top(x))<dep(top(y))) swap(x,y);
update(dfn(top(x)),dfn(x),1,k);
x=fa(top(x));
}
if(dep(x)>dep(y)) swap(x,y);
update(dfn(x),dfn(y),1,k);
}
il I query_road(I x,I y){
//操作2 求树从 x到 y结点最短路径上所有节点的值之和
I ans=0;
while(top(x)!=top(y)){
if(dep(top(x))<dep(top(y))) swap(x,y);
ans=(ans+query(dfn(top(x)),dfn(x),1)%HgS)%HgS;
x=fa(top(x));
}
if(dep(x)>dep(y)) swap(x,y);
return ans=(ans+query(dfn(x),dfn(y),1)%HgS)%HgS;
}
il void update_tree(I x,I y){
//操作3 将以x为根节点的子树内所有节点值都加上y
update(dfn(x),dfn(x)+sz(x)-1,1,y);
}
il I query_tree(I x){
//操作4 求以 x为根节点的子树内所有节点值之和
return query(dfn(x),dfn(x)+sz(x)-1,1);
}
signed main()
{
R I i,j;
I opt,x,y,z;
// freopen(".in","r",stdin);
//freopen("ans.txt","w",stdout);
n=d();m=d();root=d();HgS=d();
for(i=1;i<=n;++i) a[i]=d();
for(i=1;i<n;++i){
x=d();y=d();
add(x,y);
add(y,x);
}
dfs1(root,0,1);
dfs2(root,root);
build(1,1,n);
while(m--){
opt=d();x=d()%HgS;
if(opt==1){
y=d()%HgS;z=d()%HgS;
update_road(x,y,z);
}
if(opt==2){
y=d()%HgS;
printf("%lld\n",query_road(x,y));
}
if(opt==3){
y=d()%HgS;
update_tree(x,y);
}
if(opt==4)printf("%lld\n",query_tree(x));
}
rt 0;
}