社区讨论

请求大佬帮助

P3178[HAOI2015] 树上操作参与者 3已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mm5yjo3h
此快照首次捕获于
2026/02/28 14:46
上周
此快照最后确认于
2026/03/02 14:55
上周
查看原帖
CPP
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

#define ls(p) p << 1
#define rs(p) ((p << 1) | 1)

using namespace std;

const int N = 1e5 + 5;

struct Node {
    int to, next;
} edge[N << 1];
int head[N], cnt; 
struct Tree {
    long long tag, sum;
} tree[4 * N]; 

int n, m;
int sz[N], son[N], deep[N], id[N], fa[N], top[N], w[N], wt[N], num;  

void add(int u, int v) {
    edge[++ cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt;
}

void push_down(int p, int l, int r) {
    if (tree[p].tag) {
        int mid = (l + r) >> 1;
        tree[ls(p)].sum += (mid - l + 1) * tree[p].tag;
        tree[ls(p)].tag += tree[p].tag;
        tree[rs(p)].sum += (r - mid) * tree[p].tag;
        tree[rs(p)].tag += tree[p].tag;
        tree[p].tag = 0;
    }
}

void build(int p, int l, int r) {
    if (l == r) {
        tree[p].sum = wt[l]; 
        tree[p].tag = 0;
        return;
    }

    int mid = (l + r) >> 1;
    build(ls(p), l, mid);
    build(rs(p), mid + 1, r);
    tree[p].sum = tree[ls(p)].sum + tree[rs(p)].sum;
}

void update1(int p, int l, int r, int idx, int k) {
    if (l == r) {
        tree[p].sum += k;
        return;
    }

    int mid = (l + r) >> 1;
    if (idx <= mid) update1(ls(p), l, mid, idx, k);
    else update1(rs(p), mid + 1, r, idx, k);
    tree[p].sum = tree[ls(p)].sum + tree[rs(p)].sum;
}

void update2(int p, int l, int r, int nl, int nr, int k) {
    if (nl <= l && r <= nr) {
        tree[p].sum += (long long)(r - l + 1) * k;
        tree[p].tag += k;
        return;
    }
    push_down(p, l, r);
    int mid = (l + r) >> 1;
    if (nl <= mid) update2(ls(p), l, mid, nl, nr, k);
    if (nr > mid) update2(rs(p), mid + 1, r, nl, nr, k);
    tree[p].sum = tree[ls(p)].sum + tree[rs(p)].sum;
}

long long query(int p, int l, int r, int nl, int nr) {
    if (nl <= l && r <= nr) {
        return tree[p].sum;
    }
    push_down(p, l, r);
    int mid = (l + r) >> 1;
    long long ans = 0;
    if (nl <= mid) ans += query(ls(p), l, mid, nl, nr);
    if (nr > mid) ans += query(rs(p), mid + 1, r, nl, nr);
    return ans;
}

void dfs1(int p, int f, int dep) {
    deep[p] = dep;
    fa[p] = f;
    sz[p] = 1; 
    int maxson = -1;
    son[p] = 0;

    for (int i = head[p]; i; i = edge[i].next) {
        int v = edge[i].to;
        if (v == f) continue; 
        dfs1(v, p, dep + 1);
        sz[p] += sz[v];
        if (sz[v] > maxson) {
            son[p] = v;
            maxson = sz[v];
        }
    }
}

void dfs2(int x, int topf) {
    id[x] = ++ num;
    wt[num] = w[x];
    top[x] = topf;
    if (!son[x]) return;
    dfs2(son[x], topf);

    for (int i = head[x]; i; i = edge[i].next) {
        int v = edge[i].to;
        if (v == fa[x] || v == son[x]) continue;
        dfs2(v, v);
    }
}

void addPoint(int x, int k) {
    update1(1, 1, n, id[x], k);
}

void addTree(int x, int k) {
    update2(1, 1, n, id[x], id[x] + sz[x] - 1, k);
}

long long queryPath(int x, int y) {
    long long res = 0;

    while (top[x] != top[y]) {
        if (deep[top[x]] < deep[top[y]]) swap(x, y);
        res += query(1, 1, n, id[top[x]], id[x]);
        x = fa[top[x]];
    }

    if (deep[x] > deep[y]) swap(x, y);
    res += query(1, 1, n, id[x], id[y]);
    return res;
}

int main() {
    freopen("P3178_1.in", "r", stdin);
    freopen("1.out", "w", stdout);

    cnt = 0;
    num = 0;
    memset(head, 0, sizeof(head)); 
    memset(son, 0, sizeof(son));   

    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i ++) scanf("%d", &w[i]);
    for (int i = 1; i < n; i ++) {
        int u, v; scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }

    dfs1(1, 0, 1);
    dfs2(1, 1);
    build(1, 1, n);

    while (m --) {
        int opt, x, y;
        scanf("%d %d", &opt, &x);
        if (opt == 1) {
            scanf("%d", &y);
            addPoint(x, y);
        } else if (opt == 2) {
            scanf("%d", &y);
            addTree(x, y);
        } else {
            printf("%lld\n", queryPath(1, x));
        }
    }
    return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...