关于树链刨分的疑问

学术版

能把代码贴全吗?
by forgotmyhandle @ 2024-03-30 12:06:18


@[Jefferyz](/user/1022282) 1到底那条链有深度很深的点,但是跳一次就寄。
by xiaozengX @ 2024-03-30 12:19:16


@[xiaozengX](/user/321529) 只有打注释的2行有问题,换成dfn比较就AC了,不理解为什么跳到同一条链上dfn序应该是连续和dep等价的,为什么不能用dep比较呢?
by Jefferyz @ 2024-03-30 12:26:27


@[forgotmyhandle](/user/573377) ``` #include <bits/stdc++.h> #define int long long using namespace std; inline int read() { char c; bool flag = false; while ((c = getchar()) < '0' || c > '9') if (c == '-') flag = true; int res = c - '0'; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + c - '0'; return flag ? -res : res; } const int maxn = 6e5 + 10; int tree[maxn << 2], tag[maxn << 2], a[maxn]; int n, s[maxn], son[maxn], dep[maxn], fa[maxn], top[maxn], dfn[maxn], df, M, R, P, tmp[maxn]; int ls(int p) { return p << 1; } int rs(int p) { return p << 1 | 1; } void pushup(int p) { tree[p] = (tree[ls(p)] + tree[rs(p)]) % P; } void addtag(int p, int l, int r, int d) { tree[p] = (tree[p] + (r - l + 1) * d) % P; tag[p] = (tag[p] + d) % P; } void pushdown(int p, int l, int r) { if (!tag[p]) return; int mid = (l + r) >> 1; addtag(ls(p), l, mid, tag[p]); addtag(rs(p), mid + 1, r, tag[p]); tag[p] = 0; } void build(int p, int l, int r) { if (l == r) { tree[p] = a[l]; return; } int mid = (l + r) >> 1; build(ls(p), l, mid); build(rs(p), mid + 1, r); pushup(p); } int query(int p, int lp, int rp, int l, int r) { int ans = 0; if (lp >= l && rp <= r) return tree[p]; pushdown(p, lp, rp); int mid = (lp + rp) >> 1; if (l <= mid) ans = (ans + query(ls(p), lp, mid, l, r) % P) % P; if (r > mid) ans = (ans + query(rs(p), mid + 1, rp, l, r) % P) % P; return ans; } void update(int p, int lp, int rp, int l, int r, int d) { if (lp >= l && rp <= r) { addtag(p, lp, rp, d); return; } pushdown(p, lp, rp); int mid = (lp + rp) >> 1; if (l <= mid) update(ls(p), lp, mid, l, r, d); if (r > mid) update(rs(p), mid + 1, rp, l, r, d); pushup(p); } struct Edge { int to, w, next, from; } edge[maxn << 1], e[maxn << 1]; int head[maxn << 1], cnt; void init() { for (int i = 0; i <= n; i++) head[i] = -1; cnt = 0; } void add_edge(int u, int v, int w) { edge[cnt].to = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt++; } void dfs(int x, int ff) { fa[x] = ff; dep[x] = dep[ff] + 1; s[x] = 1; for (int i = head[x]; ~i; i = edge[i].next) { int y = edge[i].to; if (y == ff) continue; dfs(y, x); s[x] += s[y]; if (s[y] > s[son[x]]) son[x] = y; } } void dfs2(int x, int topf) { top[x] = topf; dfn[x] = ++df; if (son[x]) dfs2(son[x], topf); for (int i = head[x]; ~i; i = edge[i].next) { int y = edge[i].to; if (y == fa[x] || y == son[x]) continue; dfs2(y, y); } } int lca(int x, int y) { while (top[x] != top[y]) { if (dep[top[x]] > dep[top[y]]) x = fa[top[x]]; else y = fa[top[y]]; } return dep[x] > dep[y] ? y : x; } void path_add(int u, int v, int z) { int fu = top[u], fv = top[v]; while (fu != fv) { if (dep[fu] >= dep[fv]) update(1, 1, n, dfn[top[u]], dfn[u], z), u = fa[top[u]]; else update(1, 1, n, dfn[top[v]], dfn[v], z), v = fa[top[v]]; fu = top[u]; fv = top[v]; } if (dfn[u] >= dfn[v]) update(1, 1, n, dfn[v], dfn[u], z); else update(1, 1, n, dfn[u], dfn[v], z); } int path_chk(int u, int v) { int res = 0; int fu = top[u], fv = top[v]; while (fu != fv) { if (dep[fu] >= dep[fv]) res = (res + query(1, 1, n, dfn[top[u]], dfn[u]) % P) % P, u = fa[top[u]]; else res = (res + query(1, 1, n, dfn[top[v]], dfn[v]) % P) % P, v = fa[top[v]]; fu = top[u]; fv = top[v]; } if (dfn[u] >= dfn[v]) res += query(1, 1, n, dfn[v], dfn[u]); else res += query(1, 1, n, dfn[u], dfn[v]); return res; } void tree_add(int u, int z) { //printf("%lld %lld", dfn[u], dfn[u] + s[u] - 1); update(1, 1, n, dfn[u], dfn[u] + s[u] - 1, z); } int tree_chk(int u) { return query(1, 1, n, dfn[u], dfn[u] + s[u] - 1) % P; } signed main() { n = read(), M = read(), R = read(), P = read(); init(); for (int i = 1; i <= n; ++i) tmp[i] = read(); for (int i = 1; i < n; ++i) { int x = read(), y = read(); add_edge(x, y, 1); add_edge(y, x, 1); } dfs(R, 0); dfs2(R, R); for (int i = 1; i <= n; ++i) a[dfn[i]] = tmp[i]; build(1, 1, n); for (int i = 1; i <= M; ++i) { int opt = read(); if (opt == 1) { int x = read(), y = read(), z = read(); path_add(x, y, z); } if (opt == 2) { int x = read(), y = read(); printf("%lld\n", path_chk(x, y) % P); } if (opt == 3) { int x = read(), z = read(); tree_add(x, z); } if (opt == 4) { int x = read(); printf("%lld\n", tree_chk(x) % P); } } return 0; } ```
by Jefferyz @ 2024-03-30 12:28:26


你给的这代码用 dep 比也能过啊 [纪录](https://www.luogu.com.cn/record/153459675)
by forgotmyhandle @ 2024-03-30 15:39:27


|