1 条题解

  • 0
    @ 2025-10-8 16:51:44
    #include <bits/stdc++.h>
    using namespace std;
    #define eb emplace_back
    #define LL long long
    template <typename T> void qr(T& x)
    {
        char c = getchar(); x = 0; int f = 1;
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -1;
        for (; isdigit(c); c = getchar()) x = x * 10 + (c - '0');
        x *= f;
        
    }
    template <typename T> void qw(T x)
    {
        if (x < 0) putchar('-'), x = -x;
        if (x / 10) qw(x / 10);
        putchar(x % 10 + '0');
    }
    
    const int N = 1e6 + 10;
    vector<int> G[N];
    int n; LL v[N];
    int fa[N], siz[N], dep[N], son[N];
    void dfs1(int x, int xfa)
    {
        fa[x] = xfa;
        dep[x] = dep[xfa] + 1;
    
        siz[x] = 1;
        son[x] = 0;
        for (int y : G[x]) if (y != xfa)
        {
            dfs1(y, x);
            siz[x] += siz[y];
            if (siz[y] > siz[son[x]]) son[x] = y;
        }
    }
    
    int tsp, dfn[N], top[N];
    void dfs2(int x, int tp)
    {
        dfn[x] = ++tsp; top[x] = tp;
        if (son[x]) dfs2(son[x], tp);
        for (int y : G[x]) if (y != son[x] && y != fa[x])
            dfs2(y, y);
    }
    
    int LCA(int x, int y)
    {
        for (; top[x] != top[y]; x = fa[top[x]]) if (dep[top[x]] < dep[top[y]]) swap(x, y);
        return dep[x] < dep[y] ? x : y;
    }
    
    LL c1[N], c2[N];
    void add(LL c[], int x, LL k) { if (x == 0) return; for (; x <= n; x += x & -x) c[x] += k; }
    LL sum(LL c[], int x) { LL res = 0; for (; x >= 1; x -= x & -x) res += c[x]; return res; }
    
    LL getsum(int x)
    {
        return sum(c1, dfn[x]) * dep[x] + sum(c2, dfn[x]);
    }
    
    int main()
    {
        int m, rt; qr(n); qr(m); qr(rt);
        for (int i = 1; i <= n; i++) qr(v[i]);
        for (int i = 1, x, y; i < n; i++) qr(x), qr(y), G[x].eb(y), G[y].eb(x);
    
        dep[0] = 0;
        dfs1(rt, 0);
    
        tsp = 0;
        dfs2(rt, rt);
    
        for (int i = n; i >= 1; i--)
        {
            int l = dfn[i], r = dfn[i] + siz[i] - 1;
            add(c2, l, v[i]); add(c2, r + 1, -v[i]);
        }
    
        while (m--)
        {
            int op; scanf("%d", &op);
            if (op == 1) // 1 x k,表示将结点 x 的权值增加 k
            {
                int x; LL k; qr(x); qr(k);
                int l = dfn[x], r = dfn[x] + siz[x] - 1;
                add(c2, l, k); add(c2, r + 1, -k);
            }
            else if (op == 2) // 2 x k,表示将 x 的子树上所有结点的权值增加 k
            {
                int x; LL k; qr(x); qr(k);
                int l = dfn[x], r = dfn[x] + siz[x] - 1;
                add(c1, l, k); add(c1, r + 1, -k);
                add(c2, l, -k * (dep[x] - 1)); add(c2, r + 1, k * (dep[x] - 1));
            }
            else // 3 x y,表示求「结点 x 到结点 y 的简单路径」上所有结点的权值之和
            {
                int x, y; qr(x); qr(y);
                int lca = LCA(x, y);
                qw(getsum(x) + getsum(y) - getsum(lca) - getsum(fa[lca]));
                printf("\n");
            }
        }
        return 0;
    }
    
    • 1

    *【树上点差分】树结构区间修改、路径求和[LOJ147]DFS序4

    信息

    ID
    276
    时间
    2000ms
    内存
    512MiB
    难度
    7
    标签
    递交数
    52
    已通过
    12
    上传者