1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit:
162 MB
Submit: 7567 Solved: 3109
Description
一棵树上有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本身
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
HINT
Source
树链剖分:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> using namespace std; #define rep(i, l, r) for (int i = l; i <= r; i++) #define REP(i, l, r) for (int i = l; i >= r; i--) #define INF 2147483647 #define MAXN 1000010 int n, N = -1, M = 0, m, first[MAXN], next[MAXN], NUM[MAXN], root, T_T, c[MAXN]; int dep[MAXN], siz[MAXN], son[MAXN], fa[MAXN], top[MAXN], w[MAXN]; struct tlist {int x, y;} a[MAXN]; bool vis[MAXN]; struct Tree {int l, r, lc, rc, sum, max;} tree[MAXN]; inline void swap(int &a, int &b) {int t = a; a = b; b = t;} inline void add(int x, int y) {a[++N].x = x, a[N].y = y, next[N] = first[x], first[x] = N;} inline void dfs(int x, int d) { dep[x] = d; siz[x] = 1; vis[x] = 1; int maxsize = 0, k = 0; for (int i = first[x]; ~i; i = next[i]) if (!vis[a[i].y]) { vis[a[i].y] = 1; dfs(a[i].y, d+1); siz[x] += siz[a[i].y]; if (siz[a[i].y] > maxsize) maxsize = siz[a[i].y], k = a[i].y; } son[x] = k; } inline void DFS(int x, int T) { top[x] = T; vis[x] = 1; if (son[x]) w[son[x]] = ++M, NUM[M] = son[x], DFS(son[x], T); for (int i = first[x]; ~i; i = next[i]) if (!vis[a[i].y]) { w[a[i].y] = ++M; NUM[M] = a[i].y; DFS(a[i].y, a[i].y); } } inline void build_tree(int i, int L, int R) { tree[i].l = L, tree[i].r = R; if (L == R) {tree[i].sum = tree[i].max = c[NUM[L]]; return;} build_tree(tree[i].lc = ++m, L, (L+R) >> 1); build_tree(tree[i].rc = ++m, ((L+R) >> 1) + 1, R); tree[i].max = max(tree[tree[i].lc].max, tree[tree[i].rc].max); tree[i].sum = tree[tree[i].lc].sum + tree[tree[i].rc].sum; } inline void modify(int i, int x, int cx) { int L = tree[i].l, R = tree[i].r; if (x < L || x > R) return; if (L == R) {tree[i].sum = tree[i].max = cx; return;} modify(tree[i].lc, x, cx); modify(tree[i].rc, x, cx); tree[i].max = max(tree[tree[i].lc].max, tree[tree[i].rc].max); tree[i].sum = tree[tree[i].lc].sum + tree[tree[i].rc].sum; } inline int query_max(int i, int ql, int qr) { int L = tree[i].l, R = tree[i].r; if (qr < L || ql > R) return -INF; if (L >= ql && R <= qr) return tree[i].max; return max(query_max(tree[i].lc, ql, qr), query_max(tree[i].rc, ql, qr)); } inline int query_sum(int i, int ql, int qr) { int L = tree[i].l, R = tree[i].r; if (qr < L || ql > R) return 0; if (L >= ql && R <= qr) return tree[i].sum; return query_sum(tree[i].lc, ql, qr) + query_sum(tree[i].rc, ql, qr); } int main() { cin >> n; memset(first, -1, sizeof(first)); memset(next, -1, sizeof(next)); memset(fa, 0, sizeof(fa)); rep(i, 1, n-1) { int tx, ty; scanf("%d%d", &tx, &ty); fa[ty] = tx; if (!fa[tx]) root = tx; add(tx, ty), add(ty, tx); } rep(i, 1, n) scanf("%d", &c[i]); memset(vis, 0, sizeof(vis)); dfs(root, 1); memset(vis, 0, sizeof(vis)); w[root] = ++M, NUM[M] = root; DFS(root, root); build_tree(m = 1, 1, n); cin >> T_T; while (T_T--) { char ch[MAXN]; int tx, ty; scanf("%s", ch); scanf("%d%d", &tx, &ty); if (ch[0] == 'C') modify(1, w[tx], ty); if (ch[1] == 'M') { int f1, f2, maxans = -INF; while ((f1 = top[tx]) != (f2 = top[ty])) { if (dep[f1] < dep[f2]) swap(f1, f2), swap(tx, ty); maxans = max(maxans, query_max(1, w[f1], w[tx])); tx = fa[f1]; } if (dep[tx] < dep[ty]) swap(tx, ty); maxans = max(maxans, query_max(1, w[ty], w[tx])); cout << maxans << endl; } if (ch[1] == 'S') { int f1, f2, sumans = 0; while ((f1 = top[tx]) != (f2 = top[ty])) { if (dep[f1] < dep[f2]) swap(f1, f2), swap(tx, ty); sumans += query_sum(1, w[f1], w[tx]); tx = fa[f1]; } if (dep[tx] < dep[ty]) swap(tx, ty); sumans += query_sum(1, w[ty], w[tx]); cout << sumans << endl; } } return 0; }
时间: 2024-10-10 08:16:13