#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int g[N], sum[N], dep[N], fa[N], id[N], son[N], wp[N << 2], top[N], w[N], edge[N], nxt[N];
int tree[N << 2], put[N << 2], pre;
int n, m, r, p, cnt = 0, x, y, t, k, num = 0;
inline void add(int from, int to)
{
edge[++cnt] = to;
nxt[cnt] = g[from];
g[from] = cnt;
}
inline void findson(int x)
{
sum[x] = 1;
for(int i = g[x]; i; i = nxt[i])
{
int now = edge[i];
if(now == fa[x]){continue;}
if(fa[now] == 0)
{
fa[now] = x;
dep[now] = dep[x] + 1;
findson(now);
sum[x] += sum[now];
if(son[x] == 0 || sum[now] > sum[son[x]]){son[x] = now;}
}
}
}
inline void findtop(int x)
{
id[x] = ++num;
wp[num] = w[x];
if(!son[x]){return;}
top[son[x]] = top[x];
findtop(son[x]);
for(int i = g[x]; i; i = nxt[i])
{
int now = edge[i];
if(now != fa[now] && now != son[x])
{
top[now] = now;
findtop(now);
}
}
}
/*↓↓↓————————线段树————————↓↓↓*/
inline void build(int rt, int l, int r)
{
if(l == r)
{
tree[rt] = wp[l];
if(tree[rt] > p){tree[rt] %= p;}
return;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1]) % p;
}
inline void down(int x, int l, int r)
{
int mid = (l + r) >> 1;
int len1 = (mid - l + 1) % p;
int len2 = (r - mid) % p;
put[x << 1] += put[x];
put[x << 1] %= p;
put[x << 1 | 1] += put[x];
put[x << 1 | 1] %= p;
tree[x << 1] += put[x] * len1;
tree[x << 1] %= p;
tree[x << 1 | 1] += put[x] * len2;
tree[x << 1 | 1] %= p;
put[x] = 0;
}
inline void change(int rt, int l, int r, int x, int y, int d)
{
if(y < l || r < x){return;}
if(x <= l && r <= y)
{
int len = (r - l + 1) % p;
int e = d % p;
tree[rt] += e * len;
tree[rt] %= p;
put[rt] += d;
return;
}
if(put[rt]){down(rt, l, r);}/*如果put[x] = 0,传下去也没有意义,相当于没传,剪枝*/
int mid = (l + r) >> 1;
if(x <= mid){change(rt << 1, l, mid, x, y, d);}
if(y > mid){change(rt << 1 | 1, mid + 1, r, x, y, d);}
tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1]) % p;
}
inline void query(int rt, int l, int r, int x, int y)
{
if(y < l || r < x){return;}
if(x <= l && r <= y)
{
pre += tree[rt];
pre %= p;
return;
}
if(put[rt]){down(rt, l, r);}/*如果put[x] = 0,传下去也没有意义,相当于没传,剪枝*/
int mid = (l + r) >> 1;
if(x <= mid){query(rt << 1, l, mid, x, y);}
if(y > mid){query(rt << 1 | 1, mid + 1, r, x, y);}
tree[rt] = (tree[rt << 1] + tree[rt << 1 | 1]) % p;
}
/*↑↑↑————————线段树————————↑↑↑*/
inline void conchain(int flag, int x, int y, int d)
{
int ans = 0;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]){swap(x, y);}
if(flag == 1)
{
change(1, 1, n, id[top[x]], id[x], d);
}
if(flag == 2)
{
pre = 0;
query(1, 1, n, id[top[x]], id[x]);
ans += pre;
ans %= p;
}
x = fa[top[x]];
}
if(dep[x] > dep[y]){swap(x, y);}
if(flag == 1)
{
change(1, 1, n, id[y], id[x], d);
}
if(flag == 2)
{
pre = 0;
query(1, 1, n, id[y], id[x]);
ans += pre;
ans %= p;
cout << ans << endl;
}
}
inline void contree(int flag, int x, int d)
{
if(flag == 3)
{
change(1, 1, n, id[x], id[x] + sum[x] - 1, d);
}
if(flag == 4)
{
pre = 0;
query(1, 1, n, id[x], id[x] + sum[x] - 1);
cout << pre <<endl;
}
}
int main()
{
cin >> n >> m >> r >> p;
for(int i = 1; i <= n; i++)
{
cin >> w[i];
}
for(int i = 1; i < n; i++)
{
cin >> x >> y;
add(x, y);
add(y, x);
}
fa[r] = r;
top[r] = r;
findson(r);
findtop(r);
build(1, 1, n);
for(int i = 1; i <= m; i++)
{
cin >> t;
if(t == 1)
{
cin >> x >> y >> k;
conchain(t, x, y, k);
}
if(t == 2)
{
cin >> x >> y;
conchain(t, x, y, k);
}
if(t == 3)
{
cin >> x >> k;
contree(t, x, k);
}
if(t == 4)
{
cin >> x;
contree(t, x, k);
}
}
}
求助求助,看我的提交记录您就能明白我的苦楚……已经调了一天了,依然是T/MLE