GY程袁浩 @ 2024-07-22 15:04:27
//简单一点点了......
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
struct node {
int l, r, sum, lz;
#define l(x) tr[x].l
#define r(x) tr[x].r
#define sum(x) tr[x].sum
#define lz(x) tr[x].lz
}tr[N * 4];
int n, m, r, p;
int h[N], e[N], ne[N], w[N], wt[N], idx;
int son[N], id[N], fa[N], tsize[N], dep[N], top[N], cnt;//线段树上请用id
void add(int a, int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void pushup(int x) { sum(x) = (sum(x * 2) + sum(x * 2 + 1)) % p; }
void build(int x, int l, int r) {
l(x) = l, r(x) = r;
if (l == r) {
sum(x) = wt[l] % p;
return;
}
int mid = l + r >> 1;
build(x * 2, l, mid), build(x * 2 + 1, mid + 1, r);
pushup(x);
}
void pushdown(int x) {
(lz(x * 2) += lz(x)) %= p;
(lz(x * 2 + 1) += lz(x)) %= p;
(sum(x * 2) += lz(x) * ((r(x * 2) - l(x * 2) + 1) % p) % p) %= p;
(sum(x * 2 + 1) += lz(x) * ((r(x * 2 + 1) - l(x * 2 + 1) + 1) % p) % p) %= p;
lz(x) = 0;
}
void change(int x, int ll, int rr, int k) {
int l = l(x), r = r(x);
if (l >= ll && r <= rr) {
(sum(x) += (r - l + 1) % p * (k % p) % p) %= p;
lz(x) += k;
return;
}
pushdown(x);
int mid = l + r >> 1;
if (ll <= mid) change(x * 2, ll, rr, k);
if (rr > mid) change(x * 2 + 1, ll, rr, k);
pushup(x);
}
int qry(int x, int ll, int rr) {
int l = l(x), r = r(x);
if (l >= ll && r <= rr) return sum(x);
pushdown(x);
int mid = l + r >> 1, sum = 0;
if (ll <= mid) sum += qry(x * 2, ll, rr);
if (rr > mid) sum += qry(x * 2 + 1, ll, rr);
pushup(x);
return sum;
}
//板子,很快的线段树板子
int qryrange(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {//不在同链
if (dep[top[x]] < dep[top[y]]) swap(x, y);
(ans += qry(1, id[top[x]], id[x]) % p) %= p;//上升!
x = fa[top[x]];
}//O(log n) 类似lca???
if (dep[x] > dep[y]) swap(x, y);//注意从小到大
return (ans+qry(1,id[x],id[y])%p)%p;
}
void updrange(int x, int y, int z) {
z %= p;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
change(1, id[top[x]], id[x], z);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
change(1, id[x], id[y], z);
}
void updson(int x, int y) { change(1, id[x], id[x] + tsize[x] - 1, y); }
int qryson(int x) { return qry(1, id[x], id[x] + tsize[x] - 1); }
void dfs1(int x, int f, int deep) {
dep[x] = deep;fa[x] = f;tsize[x] = 1;int maxn = -1;
for (int i = h[x]; i != -1; i = ne[i]) {
int j = e[i];
if (j == f) continue;
dfs1(j, x, deep + 1);
tsize[x] += tsize[j];
if (tsize[j] > maxn) maxn = tsize[j],son[x] = j;
}
}
void dfs2(int x, int topf) {
id[x] = ++cnt;wt[id[x]] = w[x];top[x] = topf;
if (!son[x]) return;
dfs2(son[x], topf);
for (int i = h[x]; i != -1; i = ne[i]) {
int j = e[i];
if (j == fa[x] || j == son[x]) continue;
dfs2(j, j);//新的链
}
}
signed main() {
memset(h, -1, sizeof h);cin >> n >> m >> r >> p;
for (int i = 1; i <= n; i++) cin >> w[i];
for (int i = 1; i <= n - 1; i++) {
int x, y;cin >> x >> y;
add(x, y), add(y, x);
}
dfs1(r, 0, 1);dfs2(r, r);build(1, 1, n);//剖分+建树
for (int i = 1; i <= m; i++) {
int c, x, y, z;
cin >> c;
if (c == 1) {
cin >> x >> y >> z;
updrange(x, y, z);
}
else if(c == 2) {
cin >> x >> y;
cout << qryrange(x, y) << endl;
}
else if (c == 3) {
cin >> x >> y;
updson(x, y);
}
else {
cin >> x;
cout << qryson(x) << endl;
}
}
return 0;
}
by GY程袁浩 @ 2024-07-22 15:07:50
数组开小了