社区讨论
请求大佬帮助
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 条回复,欢迎继续交流。
正在加载回复...