1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 17022 Solved: 6939
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
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
Sample Output
4
1
2
2
10
6
5
6
5
16
题解:
1A过,树链剖分裸题,您的确会发现为什么这篇博客代码有空格,因为我是改的上海某dalao的代码,然后改了四个错之后1A了借了代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 33333;
int Sum[MAXN*4], Max[MAXN*4];
struct Edge {
int v, x;
} E[MAXN*2];
int l[MAXN];
int fa[MAXN];
int dep[MAXN];
int top[MAXN];
int p[MAXN];
int fp[MAXN];
int size[MAXN];
int son[MAXN];
int val[MAXN];
int e = 0;
int tid = 0;
void insert(int u, int v) {
E[e].v = v, E[e].x = l[u], l[u] = e++;
E[e].v = u, E[e].x = l[v], l[v] = e++;
}
void dfs(int u, int f, int d) {
dep[u] = d;
fa[u] = f;
size[u] = 1;
for (int p = l[u]; p != -1; p = E[p].x) {
int v = E[p].v;
if (v == f) continue;
dfs(v, u, d+1);
size[u] += size[v];
if ( son[u] == -1 || size[v] > size[son[u]]) {
son[u] = v;
}
}
}
void findtop(int u, int tp) {
p[u] = ++tid;
fp[p[u]] = u;
top[u] = tp;
if (son[u] == -1) return;
findtop(son[u], tp);
for (int p = l[u]; p != -1; p = E[p].x) {
int v = E[p].v;
if (v != son[u] && v != fa[u]) {
findtop(v, v);
}
}
}
int n = 0;
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
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] = val[fp[l]];
return;
}
int m = (l + r) >> 1;
build (lson);
build (rson);
pushUp(rt);
}
void update(int p, int v, int l, int r, int rt) {
if (l == r) {
Sum[rt] = Max[rt] = v;
return;
}
int m = (l + r) >> 1;
if (p <= m) update(p, v, lson);
else update(p, v, rson);
pushUp(rt);
}
int querySum(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return Sum[rt];
}
int m = (l + r) >> 1;
int ret = 0;
if (L <= m) ret += querySum(L, R, lson);
if (R > m) ret += querySum(L, R, rson);
return ret;
}
int queryMax(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return Max[rt];
}
int m = (l + r) >> 1;
int ret = -2147483647;
if (L <= m) ret = max(ret, queryMax(L, R, lson));
if (R > m) ret = max(ret, queryMax(L, R, rson));
return ret;
}
pair<int, int> myQuery(int u, int v) {
int ansMax = -233333333;
int ansSum = 0;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
ansSum += querySum(p[top[u]], p[u], 1, n, 1);
ansMax = max(ansMax, queryMax(p[top[u]], p[u], 1, n, 1));
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u, v);
ansSum += querySum(p[u], p[v], 1, n, 1);
ansMax = max(ansMax, queryMax(p[u], p[v], 1, n, 1));
return make_pair(ansSum, ansMax);
}
int main () {
memset(l, -1, sizeof(l));
memset(son, -1, sizeof(son));
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
insert(u, v);
}
dfs(1, 0, 0);
findtop(1, 1);
for (int i = 1; i <= n; i++) {
scanf("%d", &val[i]);
}
build(1, n, 1);
int q = 0;
scanf("%d", &q);
char ch[11];
for (int i = 1; i <= q; i++) {
scanf("%s", ch);
int u, v;
scanf("%d%d", &u, &v);
if (ch[1] == 'M') {
pair<int, int> a = myQuery(u, v);
printf("%d\n", a.second);
} else if (ch[1] == 'H') {
update(p[u], v, 1, n, 1);
} else if (ch[1] == 'S') {
pair<int, int> a = myQuery(u, v);
printf("%d\n", a.first);
}
}
return 0;
}