题意
给一棵树,有点权,支持更新树上一段路径增加或减少某一个值,并可以查询点权
题解
裸树链剖分,区间修改+单点查询
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
#define _for(i,a,b) for(register int i=a;i<b;++i)
#define _rep(i,a,b) for(register int i=a;i<=b;++i)
#define FREE freopen("in.txt","r",stdin)
#define FREO freopen("out.txt","w",stdout)
#define ls l, m, rt << 1
#define rs m + 1, r, rt << 1 | 1
using namespace std;
typedef long long LL;
typedef long double LD;
typedef pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e4 + 10;
const double eps = 1e-6;
const int MOD = 1e9 + 7;
int head[MAXN << 1], to[MAXN << 1], nxt[MAXN << 1], tot;
void addedge(int u, int v) {
to[tot] = v;
nxt[tot] = head[u];
head[u] = tot++;
}
int son[MAXN], id[MAXN], fa[MAXN], depth[MAXN], sz[MAXN], top[MAXN], cnt;
LL w[MAXN], a[MAXN], tr[MAXN << 2];
void Build(int l, int r, int rt) {
if (l == r) { tr[rt] = w[l]; return; }
int m = (l + r) >> 1;
Build(ls); Build(rs);
tr[rt] = 0;
}
void PushDown(int rt) {
if (tr[rt]) {
tr[rt << 1] += tr[rt];
tr[rt << 1 | 1] += tr[rt];
tr[rt] = 0;
}
}
void Update(int L, int R, LL val, int l, int r, int rt) {
if (L <= l&&r <= R) { tr[rt] += val; return; }
PushDown(rt);
int m = (l + r) >> 1;
if (L <= m) Update(L, R, val, ls);
if (R > m) Update(L, R, val, rs);
}
LL Query(int pos, int l, int r, int rt) {
if (l == r) return tr[rt];
PushDown(rt);
int m = (l + r) >> 1;
if (pos <= m) return Query(pos, ls);
else return Query(pos, rs);
}
int n, m, p;
void UpdateRange(int u, int v, LL val) {
while (top[u] != top[v]) {
if (depth[top[u]] < depth[top[v]]) swap(u, v);
Update(id[top[u]], id[u], val, 1, n, 1);
u = fa[top[u]];
}
if (depth[u] > depth[v]) swap(u, v);
Update(id[u], id[v], val, 1, n, 1);
}
void dfs1(int u, int fath, int deep) {
depth[u] = deep;
fa[u] = fath;
sz[u] = 1;
int maxSon = -1;
for (int i = head[u]; ~i; i = nxt[i]) {
if (to[i] == fath) continue;
dfs1(to[i], u, deep + 1);
sz[u] += sz[to[i]];
if (sz[to[i]] > maxSon) {
son[u] = to[i];
maxSon = sz[to[i]];
}
}
}
void dfs2(int u, int topl) {
id[u] = ++cnt;
w[cnt] = a[u];
top[u] = topl;
if (!son[u]) return;
dfs2(son[u], topl);
for (int i = head[u]; ~i; i = nxt[i]) {
if (to[i] == fa[u] || to[i] == son[u]) continue;
dfs2(to[i], to[i]);
}
}
int main() {
while (~scanf("%d%d%d", &n, &m, &p)) {
tot = 0;
memset(nxt, -1, sizeof(nxt));
memset(head, -1, sizeof(head));
_rep(i, 1, n) scanf("%lld", &a[i]);
_for(i, 1, n) {
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
cnt = 0;
memset(son, 0, sizeof(son));
dfs1(1, 0, 1);
dfs2(1, 1);
Build(1, n, 1);
char op[10];
int u, v;
LL val;
while (p--) {
scanf("%s", op);
if (op[0] == 'I') {
scanf("%d%d%lld", &u, &v, &val);
UpdateRange(u, v, val);
}
else if (op[0] == 'D') {
scanf("%d%d%lld", &u, &v, &val);
UpdateRange(u, v, -val);
}
else {
scanf("%d", &u);
printf("%lld\n", Query(id[u], 1, n, 1));
}
}
}
return 0;
}