RT,样例第二个输出一直是18,调了好久还是没找出错误QwQ感觉应该不是建树/dfs/更新子树的锅。代码风格还不错,有相应的注释,求大佬帮忙,谢谢!
#include<bits/stdc++.h>
using namespace std;
#define rep(i, m, n) for(int i = m; i <= n; i++)
#define per(i, m, n) for(int i = m; i >= n; i--)
#define pb push_back
#define vi vector<int>
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + 5;
struct SegmentTree {
int x, lazy;
} T[maxn << 2];
vi G[maxn]; //邻接表存图
int w[maxn], wt[maxn], dep[maxn], par[maxn], siz[maxn], id[maxn], son[maxn], top[maxn], rk[maxn], cnt, N, Q, mod, Root, res;
//跟第一个题解差不多,w是最初始的,wt是剖分完之后对应的,par是父节点,id是新的编号,siz是子树大小,rk好像没啥用,top是重链开始结点,res是后面query要用的。
/* ------------ dfs -----------------*/
void dfs1(int u, int k, int depth) {
par[u] = k, dep[u] = depth, siz[u] = 1;
for (int i = 0; i < (int) G[u].size(); i++) {
int v = G[u][i];
if (v == k) continue;
dfs1(v, u, depth + 1);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int t) {
top[u] = t, id[u] = ++cnt, rk[cnt] = u, wt[cnt] = w[u];
if (!son[u]) return ;
dfs2(son[u], t);
for (int i = 0; i < (int) G[u].size(); i++) {
int v = G[u][i];
if (v != par[u] && v != son[u]) dfs2(v, v);
}
}
/* --------------- 线段树部分 --------------- */
inline void pushdown(int p, int s, int t) {
int mid = (s + t) >> 1;
T[p << 1].lazy = (T[p].lazy + T[p << 1].lazy), T[p << 1 | 1].lazy = (T[p].lazy + T[p << 1 | 1].lazy);
T[p << 1].x = (T[p << 1].x + T[p].lazy * (mid - s + 1)) % mod;
T[p << 1 | 1].x = (T[p << 1 | 1].x + T[p].lazy * (t - mid)) % mod;
T[p].lazy = 0;
}
inline void build(int p, int s, int t) {
if (s == t) {
T[p].x = wt[s] % mod;
return ;
}
int mid = (s + t) >> 1;
build(p << 1, s, mid), build(p << 1 | 1, mid + 1, t);
T[p].x = (T[p << 1].x + T[p << 1 | 1].x) % mod;
}
inline void query(int l, int r, int s, int t, int p) {
if (l <= s && r >= t) { res = (res + T[p].x) % mod; return ; }
if (T[p].lazy) pushdown(p, s, t);
int mid = (s + t) >> 1;
if (l <= mid) query(l, r, s, mid, p << 1);
if (r > mid) query(l, r, mid + 1, t, p << 1 | 1);
}
inline void update(int l, int r, int c, int s, int t, int p) {
if (l <= s && r >= t) {
T[p].lazy += c;
T[p].x = (T[p].x + (t - s + 1) * c) % mod;
return ;
}
int mid = (s + t) >> 1;
if (T[p].lazy) pushdown(p, s, t);
if (l <= mid) update(l, r, c, s, mid, p << 1);
if (r > mid) update(l, r, c, mid + 1, t, p << 1 | 1);
T[p].x = (T[p << 1].x + T[p << 1 | 1].x) % mod;
}
/* -------------相应的更新区间/子树;查询区间/子树 -------------- */
inline int RangeQuery(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
res = 0;
query(id[top[x]], id[x], 1, N, 1);
ans = (ans + res) % mod;
x = par[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
res = 0;
query(id[x], id[y], 1, N, 1);
ans = (ans + res) % mod;
return ans;
}
inline void RangeUpdate(int x, int y, int k) {
k %= mod;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
update(id[top[x]], id[x], k, 1, N, 1);
x = par[top[x]];
}
if (dep[top[x]] > dep[top[y]]) swap(x, y);
update(id[x], id[y], k, 1, N, 1);
}
inline int SonQuery(int x) {
res = 0;
query(id[x], id[x] + siz[x] - 1, 1, N, 1);
return res;
}
inline void SonUpdate(int x, int c) {
update(id[x], id[x] + siz[x] - 1, c, 1, N, 1);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> N >> Q >> Root >> mod;
rep(i, 1, N) cin >> w[i];
rep(i, 1, N - 1) {
int u, v;
cin >> u >> v;
G[u].pb(v), G[v].pb(u);
}
dfs1(Root, 0, 1);
dfs2(Root, Root);
build(1, 1, N);
while (Q--) {
int opt, x, y, z;
cin >> opt;
if (opt == 1) {
cin >> x >> y >> z;
RangeUpdate(x, y, z);
} else if (opt == 2) {
cin >> x >> y;
cout << RangeQuery(x, y) << endl;
} else if (opt == 3) {
cin >> x >> y;
SonUpdate(x, y);
} else {
cin >> x;
cout << SonQuery(x) << endl;
}
}
return 0;
}