题目
题解
c
o
d
e
code
code
#include <complex>
#include <cstring>
#include <cctype>
#include <cmath>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <string>
#include <queue>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long LL;
const int maxn = 100000 + 100;
template <class T>
inline void read(T &s) {
s = 0;
T w = 1, ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -1; ch = getchar(); }
while (isdigit(ch)) { s = (s << 1) + (s << 3) + (ch ^ 48); ch = getchar(); }
s *= w;
}
int n, m, tot, cnt;
int lin[maxn], idx[maxn], dep[maxn];
LL pre[maxn], val[maxn];
int siz[maxn], fat[maxn], son[maxn], top[maxn];
struct node { int next, to; } edge[maxn * 2];
struct tree { int l, r; LL add, sum; } t[maxn * 4];
inline void add(int from, int to) {
edge[++tot].to = to;
edge[tot].next = lin[from];
lin[from] = tot;
}
void dfs1(int u, int fa, int depth) {
dep[u] = depth;
fat[u] = fa;
siz[u] = 1;
int maxson = -1;
for (int i = lin[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v == fa) continue;
dfs1(v, u, depth + 1);
siz[u] += siz[v];
if (siz[v] > maxson) {
maxson = siz[v];
son[u] = v;
}
}
}
void dfs2(int u, int tp) {
idx[u] = ++cnt;
val[cnt] = pre[u];
top[u] = tp;
if (!son[u]) return ;
dfs2(son[u], tp);
for (int i = lin[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (!idx[v])
dfs2(v, v);
}
}
void build(int p, int l, int r) {
t[p].l = l, t[p].r = r;
if (l == r) { t[p].sum = val[l]; return ; }
int mid = (l + r) >> 1;
build(p<<1, l, mid);
build(p<<1|1, mid + 1, r);
t[p].sum = t[p<<1].sum + t[p<<1|1].sum;
}
void spread(int p) {
if (t[p].add) {
t[p<<1].sum += 1ll * (t[p<<1].r - t[p<<1].l + 1) * t[p].add;
t[p<<1|1].sum += 1ll * (t[p<<1|1].r - t[p<<1|1].l + 1) * t[p].add;
t[p<<1].add += t[p].add;
t[p<<1|1].add += t[p].add;
t[p].add = 0ll;
}
}
void change(int p, int l, int r, int v) {
if (l <= t[p].l && r >= t[p].r) {
t[p].sum += 1ll* (t[p].r - t[p].l + 1) * v;
t[p].add += v;
return ;
}
spread(p);
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid) change(p<<1, l, r, v);
if (r > mid) change(p<<1|1, l, r, v);
t[p].sum = t[p<<1].sum + t[p<<1|1].sum;
}
LL query(int p, int l, int r) {
if (l <= t[p].l && r >= t[p].r) return t[p].sum;
spread(p);
LL sum = 0ll;
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid) sum += query(p<<1, l, r);
if (r > mid) sum += query(p<<1|1, l, r);
return sum;
}
void AddSubtree(int x, int y) {
change(1, idx[x], idx[x] + siz[x] - 1, y);
}
LL queryPath(int x, int y) {
LL sum = 0ll;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
sum += query(1, idx[top[x]], idx[x]);
x = fat[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
sum += query(1, idx[x], idx[y]);
return sum;
}
int main() {
read(n), read(m);
for (int i = 1; i <= n; ++i)
read(pre[i]);
for (int i = 1; i < n; ++i) {
int u, v; read(u), read(v);
add(u, v); add(v, u);
}
dfs1(1, 0, 1);
dfs2(1, 1);
build(1, 1, n);
while (m--) {
int opt, x, y;
read(opt);
if (opt == 1) {
read(x), read(y);
change(1, idx[x], idx[x], y);
}
else if (opt == 2) {
read(x), read(y);
AddSubtree(x, y);
}
else if (opt == 3) {
read(x);
printf("%lld\n", queryPath(x, 1));
}
}
return 0;
}