只对了1,3 所以没法调试(2太大了),自己测的样例都对
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N = 1e5+7;
ll mod;
struct edge{
int f,t,n;
}g[N*2];
int cnt = 1, idx=0;
int head[N];
int f[N];
int son[N];
int siz[N];
int top[N];
int dfn[N];
int ans[N];
int dep[N];
int v[N];
void add(int f,int t){
g[cnt].n = head[f];
g[cnt].t = t;
head[f] = cnt;
cnt++;
}
inline int lc(int x){
return x<<1;
}
inline int rc(int x){
return x<<1|1;
}
struct seg{
ll val, flag;
int l, r;
}tr[N*4];
void pd(int t){
if(tr[t].flag){
tr[t].flag %= mod;
tr[lc(t)].val += tr[t].flag *(tr[lc(t)].r-tr[lc(t)].l+1%mod);
tr[rc(t)].val += tr[t].flag *(tr[rc(t)].r-tr[rc(t)].l+1%mod);
tr[lc(t)].flag += tr[t].flag;
tr[rc(t)].flag += tr[t].flag;
tr[lc(t)].val %= mod; tr[rc(t)].val %= mod; tr[lc(t)].flag %= mod; tr[rc(t)].flag %= mod;
tr[t].flag = 0;
}
}
void pu(int t){
tr[t].val = tr[lc(t)].val + tr[rc(t)].val;
tr[t].val%=mod;
}
void build(int t,int l,int r){
tr[t].l = l, tr[t].r = r;
if(l==r){
tr[t].val = ans[l];
tr[t].val %= mod;
return;
}
else{
int m = (l+r)>>1;
build(lc(t),l,m);
build(rc(t),m+1,r);
pu(t);
}
}
void add(int t,int l,int r,ll w){
if(l<=tr[t].l&&tr[t].r<=r){
tr[t].val += w%mod*(tr[t].r-tr[t].l+1);
tr[t].flag += w;
tr[t].flag %= mod, tr[t].val %= mod;
return;
}
else{
pd(t);
int m = (tr[t].l+tr[t].r)>>1;
if(l<=m) add(lc(t),l,r,w);
if(r>m) add(rc(t),l,r,w);
pu(t);
}
}
ll query(int t,int l,int r){
ll ans = 0;
if(l<=tr[t].l&&tr[t].r<=r){
return tr[t].val%mod;
}
else{
pd(t);
int m = (tr[t].l+tr[t].r)>>1;
if(l<=m) ans += query(lc(t),l,r);
ans %= mod;
if(r>m) ans += query(rc(t),l,r);
ans %= mod;
pu(t);
}
return ans%mod;
}
void dfs1(int r,int fa,int depth){
dep[r] = depth;
f[r] = fa;
siz[r] = 1;
int maxson = -1;
for(int i=head[r];i;i=g[i].n){
int to = g[i].t;
if(to==fa) continue;
dfs1(to,r,depth+1);
siz[r] += siz[to];
if(siz[to]>maxson){
son[r] = to, maxson = siz[to];
}
}
//son[r] = id;
}
void dfs2(int r,int fa,int tp){
dfn[r] = ++idx;
ans[idx] = v[r]%mod;
top[r] = tp;
if(!son[r]) return;
else dfs2(son[r],r,tp);
for(int i=head[r];i;i=g[i].n){
int to = g[i].t;
if(to!=fa&&to!=son[r]) dfs2(to,r,to);
}
//son[r] = id;
}
void addpath(int x,int y,ll k){
if(dep[x]<dep[y]) swap(x,y);
while(top[x]!=top[y]){
if(dep[x]<dep[y]) swap(x,y);
add(1,dfn[top[x]],dfn[x],k);
x = f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
add(1,dfn[x],dfn[y],k);
}
ll getpath(int x,int y){
ll ans = 0;
if(dep[x]<dep[y]) swap(x,y);
while(top[x]!=top[y]){
if(dep[x]<dep[y]) swap(x,y);
ans += query(1,dfn[top[x]],dfn[x]);
ans %= mod;
x = f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans += query(1,dfn[x],dfn[y]);
return ans%mod;
}
void addzs(int x,ll k){
add(1,dfn[x],dfn[x]+siz[x]-1,k);
}
ll getzs(int x){
return query(1,dfn[x],dfn[x]+siz[x]-1)%mod;
}
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
//ifstream in("in.in");
//cin.rdbuf(in.rdbuf());
int n,m,root;
memset(son,0,sizeof son);
memset(head,0,sizeof head);
cin>>n>>m>>root>>mod;
for(int i=1;i<=n;i++) cin>>v[i];
for(int i=1;i<n;i++){
int f,t;
cin>>f>>t;
add(f,t); add(t,f);
}
dfs1(root,0,1);
dfs2(root,0,root);
build(1,1,n);
int op;
ll x,y,z;
// cout<<'\n';
// for(int i=1;i<=n;i++){
// cout<<ans[i]<<' ';
// }
// cout<<'\n';
for(int i=0;i<m;i++){
cin>>op;
if(op==1){
cin>>x>>y>>z;
addpath(x,y,z);
}
else if(op==2){
cin>>x>>y;
cout<<getpath(x,y)%mod<<'\n';
}
else if(op==3){
cin>>x>>y;
addzs(x,y);
}
else{
cin>>x;
cout<<getzs(x)%mod<<'\n';
}
// for(int i=1;i<=n;i++){
// cout<<query(1,i,i)<<' ';
// }
// cout<<'\n';
}
}
/*
5 1 2 333333
1 1 1 1 1
1 2
1 3
1 4
1 5
4 1
*/