社区讨论

样例过了,0分球条

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

讨论操作

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

当前回复
0 条
当前快照
1 份
快照标识符
@mhj21xlw
此快照首次捕获于
2025/11/03 19:26
4 个月前
此快照最后确认于
2025/11/03 19:26
4 个月前
查看原帖
CPP
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = INT_MAX;
int n, m, len, cnt;
int f[100005], top[100005], id[100005], size[100005], son[100005], dep[100005];
ll w[100005], dfs[100005];
vector<int> G[100005];
struct node {
    int l, r;
    ll sum, add;
} tree[400005];
void dfs1(int u, int fa, int d) {
    f[u] = fa, size[u] = 1, dep[u] = d;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v == fa) continue;
        dfs1(v, u, d + 1);
        size[u] += size[v];
        if (size[v] > size[son[u]])
            son[u] = v;
    }
}
void dfs2(int u, int t) {
    top[u] = t, id[u] = ++cnt, dfs[cnt] = w[u];
    if (!son[u]) return;
    dfs2(son[u], t);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v != f[u] && v != son[u])
            dfs2(v, v);
    }
}
inline void pushup(int k) {
    tree[k].sum = tree[k * 2].sum + tree[k * 2 + 1].sum;
}
inline void pushdown(int x) {
    tree[x * 2].sum += tree[x].add * (tree[x * 2].r - tree[x * 2].l + 1);
    tree[x * 2 + 1].sum += tree[x].add * (tree[x * 2 + 1].r - tree[x * 2 + 1].l + 1);
    tree[x * 2].add += tree[x].add;
    tree[x * 2 + 1].add += tree[x].add;
    tree[x].add = 0;
}
void build(int now, int l, int r) {
    tree[now].l = l, tree[now].r = r;
    if (l == r) {
        tree[now].sum = dfs[l];
        return;
    }
    int mid = (l + r) / 2;
    build(now * 2, l, mid);
    build(now * 2 + 1, mid + 1, r);
    pushup(now);
}
void add(int now, int x, int y, ll val) {
	int l = tree[now].l, r = tree[now].r;
    if (x <= l && r <= y) {
        tree[now].add += val;
        tree[now].sum += val * (tree[now].r - tree[now].l + 1);
        return;
    }
	pushdown(now);
    int mid = (l + r) / 2;
    if (x <= mid) add(now * 2, x, y, val);
    if (y > mid) add(now * 2 + 1, x, y, val);
    pushup(now);
}
ll query(int now, int x, int y) {
    int l = tree[now].l, r = tree[now].r;
    if (x <= l && r <= y) return tree[now].sum;
    pushdown(now);
    int mid = (l + r) / 2;
	ll ans = 0;
    if (x <= mid) ans += query(now * 2, x, y);
    if (y > mid) ans += query(now * 2 + 1, x, y);
    return ans;
}
ll sumtree(int x, int y) {
    int tx = top[x], ty = top[y];
    ll ans = 0;
    while (tx != ty) {
        if (dep[tx] >= dep[ty]) {
            ans += query(1, id[tx], id[x]);
            x = f[tx], tx = top[x];
        } else {
            ans += query(1, id[ty], id[y]);
            y = f[ty], ty = top[y];
        }
    }
    if (id[x] <= id[y])
        ans += query(1, id[x], id[y]);
    else
        ans += query(1, id[y], id[x]);
    return ans;
}
inline void addtree(int x, int a) {
	add(1, id[x], id[x] + size[x] - 1, a);
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &w[i]);
    for (int i = 1; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        G[x].push_back(y), G[y].push_back(x);
    }
    dfs1(1, 0, 1);
    dfs2(1, 1);
    build(1, 1, n);
    while (m--) {
		int op, x;
		ll a;
		scanf("%d%d", &op, &x);
		if (op == 1) {
			scanf("%lld", &a);
			add(1, id[x], id[x], a);
		} else if (op == 2) {
			scanf("%lld", &a);
			addtree(id[x], a);
		} else {
			printf("%lld\n", sumtree(1, x));
		}
	}
    return 0;
}

回复

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

正在加载回复...