洛谷P6329 【模板】点分树 / 震波 题解 动态点分治/点分树 模板题

题目链接:https://www.luogu.com.cn/problem/P6329

思路全部来自 OI WIKI:https://oi.wiki/graph/dynamic-tree-divide/

按照自己的码风写了一下。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5, maxm = maxn * 200;

int n, m, value[maxn], rt, fa[maxn], ans;
bool vis[maxn];
vector<int> g[maxn];

struct LCA {

    int dep[maxn], fa[maxn][17];

    void dfs(int u, int p) {
        fa[u][0] = p;
        dep[u] = dep[p] + 1;
        for (auto v : g[u])
            if (v != p)
                dfs(v, u);
    }

    void build() {
        dfs(1, 0);
        for (int i = 1; i < 17; i++)
            for (int u = 1; u <= n; u++)
                fa[u][i] = fa[ fa[u][i-1] ][i-1];
    }

    int lca(int x, int y) {
        if (dep[x] < dep[y])
            swap(x, y);
        for (int i = 16; i >= 0; i--) {
            int p = fa[x][i];
            if (dep[p] >= dep[y]) x = p;
        }
        if (x == y)
            return x;
        for (int i = 16; i >= 0; i--)
            if (fa[x][i] != fa[y][i])
                x = fa[x][i], y = fa[y][i];
        return fa[x][0];
    }

    int dis(int x, int y) {
        return dep[x] + dep[y] - 2 * dep[lca(x, y)];
    }

} lca;

struct Segtree {

    int rt[maxn], ls[maxm], rs[maxm], tr[maxm], idx;

    void push_up(int u) {
        tr[u] = tr[ ls[u] ] + tr[ rs[u] ];
    }

    void update(int p, int val, int l, int r, int &u) {
        if (!u) u = ++idx;
        if (l == r) {
            tr[u] += val;
            return;
        }
        int mid = l + r >> 1;
        (p <= mid) ? update(p, val, l, mid, ls[u]) : update(p, val, mid+1, r, rs[u]);
        push_up(u);
    }

    int query(int L, int R, int l, int r, int u) {
        if (!u) return 0;
        if (L <= l && r <= R)
            return tr[u];
        int res = 0, mid = l + r >> 1;
        if (L <= mid)
            res += query(L, R, l, mid, ls[u]);
        if (R > mid)
            res += query(L, R, mid+1, r, rs[u]);
        return res;
    }

} info_fa, info_me;

int get_sz(int u, int p) {
    if (vis[u]) return 0;
    int sz = 1;
    for (auto v : g[u])
        if (v != p)
            sz += get_sz(v, u);
    return sz;
}

int get_wc(int u, int p, int tot, int &wc) {
    if (vis[u]) return 0;
    int sz = 1, mx = 0;
    for (auto v : g[u]) {
        if (v != p) {
            int tmp = get_wc(v, u, tot, wc);
            sz += tmp;
            mx = max(mx, tmp);
        }
    }
    mx = max(mx, tot - sz);
    if (mx <= tot / 2)
        wc = u;
    return sz;
}

void dfs_me(int u, int p, int d, int x) {
    if (vis[u]) return;
    info_me.update(d, value[u], 0, n, info_me.rt[x]);
    for (auto v : g[u])
        if (v != p)
            dfs_me(v, u, d+1, x);
}

void dfs_fa(int u, int p, int d, int x) {
    if (vis[u]) return;
    info_fa.update(d, value[u], 0, n, info_fa.rt[x]);
    for (auto v : g[u])
        if (v != p)
            dfs_fa(v, u, d+1, x);
}

void pre(int u) {
    dfs_me(u, 0, 0, u);
    vis[u] = true;
    for (auto v : g[u]) {
        if (vis[v]) continue;
        int x;
        get_wc(v, u, get_sz(v, u), x);
        dfs_fa(v, u, 1, x);
        fa[x] = u;
        pre(x);
    }
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", value + i);
    }
    for (int i = 1, u, v; i < n; i++) {
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    lca.build();
    get_wc(1, 0, n, rt);
    pre(rt);
    for (int i = 0, op; i < m; i++) {
        scanf("%d", &op);
        if (op == 0) {  // 0 x k
            int x, k;
            scanf("%d%d", &x, &k);
            x ^= ans;
            k ^= ans;
            ans = info_me.query(0, k, 0, n, info_me.rt[x]);
            for (int u = x; fa[u]; u = fa[u]) {
                int p = fa[u];
                int d = lca.dis(x, p);
                if (d <= k) {
                    ans += info_me.query(0, k-d, 0, n, info_me.rt[p]);
                    ans -= info_fa.query(0, k-d, 0, n, info_fa.rt[u]);
                }
            }
            printf("%d\n", ans);
        }
        else {  // 1 x y
            int x, y;
            scanf("%d%d", &x, &y);
            x ^= ans;
            y ^= ans;
            info_me.update(0, -value[x], 0, n, info_me.rt[x]);
            info_me.update(0, y, 0, n, info_me.rt[x]);
            for (int u = x; fa[u]; u = fa[u]) {
                int p = fa[u];
                int d = lca.dis(x, p);
                info_me.update(d, -value[x], 0, n, info_me.rt[p]);
                info_me.update(d, y, 0, n, info_me.rt[p]);
                info_fa.update(d, -value[x], 0, n, info_fa.rt[u]);
                info_fa.update(d, y, 0, n, info_fa.rt[u]);
            }
            value[x] = y;
        }
    }
    return 0;
}
posted @ 2026-01-13 23:17  quanjun  阅读(4)  评论(0)    收藏  举报