这份代码中,线段树中没加取模,可以 AC。
#include <bits/stdc++.h>
#define int long long
using namespace std;
class SegTree {
private:
struct Node {
int Left, Right, Sum, Delta;
Node *Lchild, *Rchild;
};
public:
Node *Tree = new Node;
void build(Node *cur, int L, int R) {
cur->Left = L;
cur->Right = R;
if (L != R) {
cur->Lchild = new Node;
cur->Rchild = new Node;
cur->Sum = 0;
build(cur->Lchild, L, (L + R) >> 1);
build(cur->Rchild, ((L + R) >> 1) + 1, R);
} else {
cur->Lchild = cur->Rchild = NULL;
cur->Sum = 0;
};
}
int query(Node *cur, int L, int R) {
int ans = 0;
if (L <= cur->Left && cur->Right <= R)
ans += cur->Sum + cur->Delta * (cur->Right - cur->Left + 1);
else {
cur->Lchild->Delta += cur->Delta;
cur->Rchild->Delta += cur->Delta;
cur->Delta = 0;
if (L <= (cur->Left + cur->Right) >> 1)
ans += query(cur->Lchild, L, R);
if (R > (cur->Left + cur->Right) >> 1)
ans += query(cur->Rchild, L, R);
cur->Sum = cur->Lchild->Sum + cur->Lchild->Delta * (cur->Lchild->Right - cur->Lchild->Left + 1) + cur->Rchild->Sum + cur->Rchild->Delta * (cur->Rchild->Right - cur->Rchild->Left + 1);;
}
return ans;
}
void update(Node *cur, int Dex, int Change) {
if (cur->Left == cur->Right) {
cur->Sum = Change;
cur->Delta = 0;
} else {
cur->Lchild->Delta += cur->Delta;
cur->Rchild->Delta += cur->Delta;
cur->Delta = 0;
if (Dex <= (cur->Left + cur->Right) >> 1)update(cur->Lchild, Dex, Change);
if (Dex > (cur->Left + cur->Right) >> 1)update(cur->Rchild, Dex, Change);
cur->Sum = cur->Lchild->Sum + cur->Lchild->Delta * (cur->Lchild->Right - cur->Lchild->Left + 1) + cur->Rchild->Sum + cur->Rchild->Delta * (cur->Rchild->Right - cur->Rchild->Left + 1);
}
}
void secupdate(Node *cur, int L, int R, int Change) {
if (L <= cur->Left && cur->Right <= R)
cur->Delta += Change;
else {
if (L <= (cur->Left + cur->Right) >> 1)secupdate(cur->Lchild, L, R, Change);
if (R > (cur->Left + cur->Right) >> 1)secupdate(cur->Rchild, L, R, Change);
cur->Sum = cur->Lchild->Sum + cur->Lchild->Delta * (cur->Lchild->Right - cur->Lchild->Left + 1) + cur->Rchild->Sum + cur->Rchild->Delta * (cur->Rchild->Right - cur->Rchild->Left + 1);
}
}
};
const int N = 100001;
int n, q, root, mod, v[N];
int cnt, size[N], dep[N], fa[N], son[N], top[N], id[N], rk[N];
vector<int> g[N];
SegTree S;
void dfs1(int u, int f) {
// cout << "dfs1(" << u << ", " << f << ")" << endl;
size[u] = 1;
dep[u] = dep[fa[u]] + 1;
for (int v: g[u]) {
// cout << v << " ";
// cout << "# " << v << endl;
if (v == f) continue;
fa[v] = u;
dfs1(v, u);
size[u] += size[v];
if (size[son[u]] < size[v])
son[u] = v;
}
// cout << endl;
}
void dfs2(int u, int f, int tp) {
top[u] = tp;
id[u] = ++cnt;
rk[cnt] = u;
if (son[u]) dfs2(son[u], u, tp);
for (int v: g[u])
if (v != f && v != son[u])
dfs2(v, u, v);
}
void op1(int x, int y, int k) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
S.secupdate(S.Tree, id[top[x]], id[x], k);
x = fa[top[x]];
}
if (id[x] > id[y]) swap(x, y);
S.secupdate(S.Tree, id[x], id[y], k);
}
int op2(int x, int y) {
int ret = 0;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
(ret += S.query(S.Tree, id[top[x]], id[x])) %= mod;
x = fa[top[x]];
}
if (id[x] > id[y]) swap(x, y);
return (ret + S.query(S.Tree, id[x], id[y])) % mod;
}
signed main() {
cin >> n >> q >> root >> mod;
for (int i = 1; i <= n; i++)
cin >> v[i];
for (int i = 1; i < n; i++) {
int x, y;
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
// for (int i = 1; i < n; i++) {
// cout << i << ": ";
// for (int j: g[i])
// cout << j << " ";
// cout << endl;
// }
dfs1(root, -1);
dfs2(root, -1, root);
// for (int i = 1; i <= n; i++)
// cout << fa[i] << " ";
// cout << endl;
// for (int i = 1; i <= n; i++)
// cout << dep[i] << " ";
// cout << endl;
// for (int i = 1; i <= n; i++)
// cout << top[i] << " ";
// cout << endl;
// for (int i = 1; i <= n; i++)
// cout << id[i] << " ";
// cout << endl;
// for (int i = 1; i <= n; i++)
// cout << size[i] << " ";
// cout << endl;
S.build(S.Tree, 1, n);
for (int i = 1; i <= n; i++)
S.update(S.Tree, i, v[rk[i]]);
while (q--) {
int op;
cin >> op;
if (op == 1) {
int x, y, k;
cin >> x >> y >> k;
op1(x, y, k);
} else if (op == 2) {
int x, y;
cin >> x >> y;
cout << op2(x, y) << endl;
} else if (op == 3) {
int x, y;
cin >> x >> y;
S.secupdate(S.Tree, id[x], id[x] + size[x] - 1, y);
} else if (op == 4) {
int x;
cin >> x;
cout << S.query(S.Tree, id[x], id[x] + size[x] - 1) % mod << endl;
}
}
return 0;
}