rt,想敲一下板子,结果不会调了(
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ls (u << 1)
#define rs (u << 1 | 1)
const ll N = 1e5 + 10;
ll n, m, r, p, op, x, y, z, cnt, tot;
struct edge{
ll to, nxt;
}e[N << 1];
struct Tree{
ll sum, lazy;
}tr[N << 2];
ll head[N], a[N], tp[N], sz[N], dep[N], son[N], fa[N], dfn[N], rk[N];
void add(ll x, ll y){
tr[++tot] = {y, head[x]};
head[x] = tot;
}
void dfs1(ll u, ll pa){
fa[u] = pa; dep[u] = dep[pa] + 1; sz[u] = 1;
for(ll i = head[u]; i; i = e[i].nxt){
ll v = e[i].to;
if(v == pa) continue;
dfs1(v, u);
sz[u] += sz[v];
if(sz[son[u]] < sz[v]) son[u] = v;
}
}
void dfs2(ll u, ll tp_fa){
dfn[u] = ++cnt; rk[cnt] = u; tp[u] = tp_fa;
if(son[u]) dfs2(son[u], tp[u]);
for(ll i = head[u]; i; i = e[i].nxt){
ll v = e[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
void pushup(ll u){
tr[u].sum = (tr[ls].sum + tr[rs].sum) % p;
}
void pushdown(ll u, ll l, ll r){
if(!tr[u].lazy) return;
ll mid = (l + r) >> 1;
tr[ls].sum = (tr[ls].sum + tr[u].lazy * (mid - l + 1) % p) % p;
tr[rs].sum = (tr[rs].sum + tr[u].lazy * ( r - mid) % p) % p;
tr[ls].lazy = (tr[ls].lazy + tr[u].lazy) % p;
tr[rs].lazy = (tr[rs].lazy + tr[u].lazy) % p;
tr[u].lazy = 0;
}
void build(ll u, ll l, ll r){
if(l == r){
tr[u].sum = a[rk[l]] % p;
return;
}
ll mid = (l + r) >> 1;
build(ls, l, mid); build(rs, mid + 1, r);
pushup(u);
}
void update(ll u, ll l, ll r, ll L, ll R, ll val){
if(L <= l && r <= R){
tr[u].sum = (tr[u].sum + (r - l + 1) * val % p) % p;
tr[u].lazy = (tr[u].lazy + val) % p;
return;
}
pushdown(u, l, r);
ll mid = (l + r) >> 1;
if(L <= mid) update(ls, l, mid, L, R, val);
if(mid < R) update(rs, mid + 1, r, L, R, val);
pushup(u);
}
ll query(ll u, ll l, ll r, ll L, ll R){
if(L <= l && r <= R) return tr[u].sum % p;
pushdown(u, l, r);
ll mid = (l + r) >> 1, ans = 0;
if(L <= mid) ans = (ans + query(ls, l, mid, L, R)) % p;
if(mid < R) ans = (ans + query(rs, mid + 1, r, L, R)) % p;
return ans;
}
void uv_update(ll u, ll v, ll w){
while(tp[u] != tp[v]){
if(dep[tp[u]] < dep[tp[v]]) swap(u, v);
update(1, 1, n, dfn[tp[u]], dfn[u], w);
u = fa[tp[u]];
}
if(dep[u] < dep[v]) swap(u, v);
update(1, 1, n, dfn[v], dfn[u], w);
}
ll uv_query(ll u, ll v){
ll ans = 0;
while(tp[u] != tp[v]){
if(dep[tp[u]] < dep[tp[v]]) swap(u, v);
ans = (ans + query(1, 1, n, dfn[tp[u]], dfn[u])) % p;
u = fa[tp[u]];
}
if(dep[u] < dep[v]) swap(u, v);
ans = (ans + query(1, 1, n, dfn[v], dfn[u])) % p;
return ans;
}
int main(){
cin >> n >> m >> r >> p;
for(ll i = 1; i <= n; i++) scanf("%lld", &a[i]);
for(ll i = 1; i < n; i++){
scanf("%lld %lld", &x, &y);
add(x, y); add(y, x);
}
dfs1(r, 0); dfs2(r, r);
build(1, 1, n);
while(m--){
scanf("%lld %lld", &op, &x);
if(op == 1){
scanf("%lld %lld", &y, &z);
uv_update(x, y, z);
}else if(op == 2){
scanf("%lld", &y);
printf("%lld\n", uv_query(x, y));
}else if(op == 3){
scanf("%lld", &y);
update(1, 1, n, dfn[x], dfn[x] + sz[x] - 1, y);
}else printf("%lld\n", query(1, 1, n, dfn[x], dfn[x] + sz[x] - 1));
}
return 0;
}