题目
题目描述
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
I. CHANGE u t : 把结点u的权值改为t
II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III. QSUM u v: 询问从点u到点v的路径上的节点的权值和
注意:从点u到点v的路径上的节点包括u和v本身
输入输出格式
输入格式:
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来一行n个整数,第i个整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出格式:
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
输入输出样例
输入样例#1:
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
输出样例#1:
4
1
2
2
10
6
5
6
5
16
题解
- 树链剖分板子题yyy
- 树链剖分讲解qwq
- 维护一个支持单点修改+区间查询的线段树即可
询问输出打反我怕不是个zz这种题一打就150+行,真的烦
code
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <vector>
#include <string>
#include <cstring>
#include <iomanip>
#include <complex>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long LL;
const int maxn = 30000 + 100;
const int inf = 0x3f3f3f3f;
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;
}
char ch[10];
int n, tot, m, cnt;
int lin[maxn], pre[maxn], val[maxn], top[maxn];
int siz[maxn], dep[maxn], son[maxn], idx[maxn], fat[maxn];
struct node { int next, to; } edge[maxn << 1];
struct tree { int l, r; LL dat, 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) {
siz[u] = 1;
fat[u] = fa;
dep[u] = depth;
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) {
top[u] = tp;
idx[u] = ++cnt;
val[cnt] = pre[u];
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].dat = val[l];
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;
t[p].dat = max(t[p<<1].dat, t[p<<1|1].dat);
}
void change(int p, int x, int v) {
if (t[p].l == t[p].r) {
t[p].dat = v;
t[p].sum = v;
return ;
}
int mid = (t[p].l + t[p].r) >> 1;
if (x <= mid) change(p<<1, x, v);
else change(p<<1|1, x, v);
t[p].sum = t[p<<1].sum + t[p<<1|1].sum;
t[p].dat = max(t[p<<1].dat, t[p<<1|1].dat);
}
LL queryMax(int p, int l, int r) {
if (l <= t[p].l && r >= t[p].r) return t[p].dat;
LL ans = -(1<<30);
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid) ans = max(ans, queryMax(p<<1, l, r));
if (r > mid) ans = max(ans, queryMax(p<<1|1, l, r));
return ans;
}
LL querySum(int p, int l, int r) {
if (l <= t[p].l && r >= t[p].r) return t[p].sum;
LL ans = 0ll;
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid) ans += querySum(p<<1, l, r);
if (r > mid) ans += querySum(p<<1|1, l, r);
return ans;
}
LL TreeSum(int x, int y) {
LL ans = 0ll;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += querySum(1, idx[top[x]], idx[x]);
x = fat[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
// cout << x << ' ' << y << endl;
ans += querySum(1, idx[x], idx[y]);
return ans;
}
LL TreeMax(int x, int y) {
LL ans = -(1<<30);
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans = max(ans, queryMax(1, idx[top[x]], idx[x]));
x = fat[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans = max(ans, queryMax(1, idx[x], idx[y]));
}
int main() {
freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);
read(n);
for (int i = 1; i < n; ++i) {
int x, y; read(x), read(y);
add(x, y); add(y, x);
}
for (int i = 1; i <= n; ++i) read(pre[i]);
dfs1(1, 0, 1);
dfs2(1, 1);
build(1, 1, n);
read(m);
while (m--) {
static char ch[10];
static int x, y;
scanf("%s", ch);
if (ch[1] == 'H') { // CHANGE
read(x), read(y);
change(1, idx[x], y);
}
else if (ch[1] == 'S') { // QSUM
read(x), read(y);
printf("%lld\n", TreeSum(x, y));
}
else if (ch[1] == 'M') { // QMAX
read(x), read(y);
printf("%lld\n", TreeMax(x, y));
}
}
return 0;
}