Linge_Zzzz @ 2023-10-29 15:55:00
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,r,P;
int a[N];
struct edge{
int v,nxt;
}e[N*2];
int head[N],cnt=2;
void add(int u,int v){
e[cnt].v=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
int dep[N],fa[N],son[N],siz[N];
int w[N],dfn[N],top[N],num=0;
void dfs1(int u,int fat){
dep[u]=dep[fat]+1;
fa[u]=fat;
siz[u]=1;
int mx=-1;
for(int i=head[u];i;i=e[i].nxt){
if(e[i].v==fat)continue;
dfs1(e[i].v,u);
siz[u]+=siz[e[i].v];
if(siz[e[i].v]>mx){
mx=siz[e[i].v];
son[u]=e[i].v;
}
}
}
void dfs2(int u,int topf){
dfn[u]=++num;
w[num]=a[u];
top[u]=topf;
if(!son[u])return;
dfs2(son[u],topf);
for(int i=head[u];i;i=e[i].nxt){
if(!dfn[e[i].v])
dfs2(e[i].v,e[i].v);
}
}
struct node{
int l,r;
int val,lazy;
}t[N*4];
void pushup(int p){
t[p].val=(t[p*2].val+t[p*2+1].val)%P;
}
void pushdown(int p){
t[p*2].val=(t[p*2].val+(t[p*2].r-t[p*2].l-1)*t[p].lazy)%P;
t[p*2+1].val=(t[p*2+1].val+(t[p*2+1].r-t[p*2+1].l-1)*t[p].lazy)%P;
t[p*2].lazy=(t[p*2].lazy+t[p].lazy)%P;
t[p*2+1].lazy=(t[p*2+1].lazy+t[p].lazy)%P;
t[p].lazy=0;
}
void build(int p,int l,int r){
t[p].l=l,t[p].r=r;
if(l==r){
t[p].val=w[l]%P;
return;
}
int m=l+r>>1;
build(p*2,l,m);
build(p*2+1,m+1,r);
pushup(p);
}
int query(int p,int l,int r){
if(l<=t[p].l&&t[p].r<=r)return t[p].val;
int m=t[p].l+t[p].r>>1,ans=0;
pushdown(p);
if(l<=m)ans=(ans+query(p*2,l,r))%P;
if(r>m)ans=(ans+query(p*2+1,l,r))%P;
return ans;
}
void update(int p,int l,int r,int val){
if(l<=t[p].l&&t[p].r<=r){
t[p].val=(t[p].val+(t[p].r-t[p].l+1)*val)%P;
t[p].lazy=(t[p].lazy+val)%P;
return;
}
int m=t[p].l+t[p].r>>1;
pushdown(p);
if(l<=m)update(p*2,l,r,val);
if(r>m)update(p*2+1,l,r,val);
pushup(p);
}
int treequery(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=(ans+query(1,dfn[top[x]],dfn[x]))%P;
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans=(ans+query(1,dfn[x],dfn[y]))%P;
return ans;
}
void treeupdate(int x,int y,int val){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(1,dfn[top[x]],dfn[x],val%P);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
update(1,dfn[x],dfn[y],val);
}
void treesonsupdate(int u,int val){
update(1,dfn[u],dfn[u]+siz[u]-1,val%P);
}
int treesonsquery(int u){
return query(1,dfn[u],dfn[u]+siz[u]-1);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m>>r>>P;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++){
int x,y;
cin>>x>>y;
add(x,y),add(y,x);
}
dfs1(r,0);
dfs2(r,r);
build(1,1,n);
while(m--){
int op,x,y,z;
cin>>op;
if(op==1){
cin>>x>>y>>z;
treeupdate(x,y,z);
}else if(op==2){
cin>>x>>y;
cout<<treequery(x,y)%P<<'\n';
}else if(op==3){
cin>>x>>z;
treesonsupdate(x,z);
}else if(op==4){
cin>>x;
cout<<treesonsquery(x)%P<<'\n';
}
}
return 0;
}
by diandian2020 @ 2023-10-29 16:00:23
pushdown那里应该是r-l+1
by Linge_Zzzz @ 2023-10-29 16:11:40
@diandian2020 草,果然挂这了,已关,感谢大佬
by MC小萌新 @ 2023-10-29 16:19:08
写树剖写的
by diandian2020 @ 2023-10-29 17:02:37
@SANESSS My pleasure.