题解
注意负数!!
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 10;
int n, m, k;
namespace chain {//树链剖分板子
int a[N];//实际点权
struct egde {
int to, next;
} e[N];
int head[N], tot;
void add(int u, int v) {//一次建双边
e[++tot] = {v, head[u]};
head[u] = tot;
e[++tot] = {u, head[v]};
head[v] = tot;
}
int dep[N];//深度
int f[N];//父节点
int son[N];//重儿子
int sz[N];//子树大小
void dfs1(int u, int fa) {
f[u] = fa;
dep[u] = dep[fa] + 1;
sz[u] = 1;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (v != fa) {
dfs1(v, u);
sz[u] += sz[v];
if (sz[v] > sz[son[u]])
son[u] = v;
}
}
}
int dfn = 0, id[N], top[N];
int w[N];//树链剖分后的点权
void dfs2(int u, int tp) {
id[u] = ++dfn;
top[u] = tp;
w[dfn] = a[u];
if (son[u])dfs2(son[u], tp);
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (v != f[u] && v != son[u]) {
dfs2(v, v);
}
}
}
}
using namespace chain;
namespace Segment_Tree {//线段树板子
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
int Max[N * 4];//区间最大值
int sum[N * 4];//区间和
void pushup(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
}
void build(int l, int r, int rt) {
if (l == r) {
sum[rt] = Max[rt] = w[l];//可能需要修改
return;
}
int mid = l + r >> 1;
build(lson);
build(rson);
pushup(rt);
}
void update(int pos, int t, int l, int r, int rt) {
if (l == r) {
sum[rt] = Max[rt] = t;
return;
}
int mid = l + r >> 1;
if (pos <= mid)update(pos, t, lson);
else update(pos, t, rson);
pushup(rt);
}
int query_sum(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return sum[rt];
}
int mid = l + r >> 1;
int res = 0;
if (L <= mid)res += query_sum(L, R, lson);
if (R > mid)res += query_sum(L, R, rson);
return res;
}
int query_max(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return Max[rt];
}
int mid = l + r >> 1;
int res = -INF;//注意负数!!
if (L <= mid)res = max(res, query_max(L, R, lson));
if (R > mid)res = max(res, query_max(L, R, rson));
return res;
}
}
using namespace Segment_Tree;
int qsum(int u, int v) {
int res = 0;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]])swap(u, v);
res += query_sum(id[top[u]], id[u], 1, n, 1);
u = f[top[u]];
}
if (dep[u] > dep[v])swap(u, v);
res += query_sum(id[u], id[v], 1, n, 1);
return res;
}
int qmax(int u, int v) {
int res = -INF;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]])swap(u, v);
res = max(res, query_max(id[top[u]], id[u], 1, n, 1));
u = f[top[u]];
}
if (dep[u] > dep[v])swap(u, v);
res = max(res, query_max(id[u], id[v], 1, n, 1));
return res;
}
string op;
int main() {
ios::sync_with_stdio(0);
cin >> n;
for (int i = 1, u, v; i < n; ++i) {
cin >> u >> v;
add(u, v);
}
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
dfs1(1, 0);
dfs2(1, 1);
build(1, n, 1);
cin >> m;
for (int i = 1, u, v; i <= m; ++i) {
cin >> op >> u >> v;
if (op == "QMAX") {
cout << qmax(u, v) << endl;
} else if (op == "CHANGE") {
update(id[u], v, 1, n, 1);
} else if (op == "QSUM") {
cout << qsum(u, v) << endl;
}
}
return 0;
}