[BZOJ1036] [ZJOI2008] 树的统计Count (LCT)
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
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
1
2
2
10
6
5
6
5
16
HINT
Source
Solution
LCT维护点权和与点权最大值。注意用cin/cout会RE!!!
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct LCT 4 { 5 int fa, c[2], rev, val, sum, max; 6 inline int& operator[] (int rhs) 7 { 8 return c[rhs]; 9 } 10 }a[30005]; 11 int sta[30005], top; 12 13 void push_up(int k) 14 { 15 a[k].sum = a[a[k][0]].sum + a[a[k][1]].sum + a[k].val; 16 a[k].max = max(max(a[a[k][0]].max, a[a[k][1]].max), a[k].val); 17 } 18 19 void push_down(int k) 20 { 21 if(a[k].rev) 22 { 23 a[a[k][0]].rev ^= 1, a[a[k][1]].rev ^= 1; 24 swap(a[k][0], a[k][1]), a[k].rev = 0; 25 } 26 } 27 28 bool isroot(int x) 29 { 30 return a[a[x].fa][0] != x && a[a[x].fa][1] != x; 31 } 32 33 void rotate(int x) 34 { 35 int y = a[x].fa, z = a[y].fa; 36 int dy = a[y][1] == x, dz = a[z][1] == y; 37 if(!isroot(y)) a[z][dz] = x; 38 a[y][dy] = a[x][dy ^ 1], a[a[x][dy ^ 1]].fa = y; 39 a[x][dy ^ 1] = y, a[y].fa = x, a[x].fa = z; 40 push_up(y); 41 } 42 43 void splay(int x) 44 { 45 sta[top = 1] = x; 46 for(int i = x; !isroot(i); i = a[i].fa) 47 sta[++top] = a[i].fa; 48 while(top) 49 push_down(sta[top--]); 50 while(!isroot(x)) 51 { 52 int y = a[x].fa, z = a[y].fa; 53 if(!isroot(y)) 54 if(a[y][1] == x ^ a[z][1] == y) rotate(x); 55 else rotate(y); 56 rotate(x); 57 } 58 push_up(x); 59 } 60 61 void access(int x) 62 { 63 for(int i = 0; x; x = a[x].fa) 64 splay(x), a[x][1] = i, i = x; 65 } 66 67 void make_root(int x) 68 { 69 access(x), splay(x), a[x].rev ^= 1; 70 } 71 72 int main() 73 { 74 int n, q, u, v; 75 char s[10]; 76 scanf("%d", &n), a[0].max = -33333; 77 for(int i = 1; i < n; i++) 78 scanf("%d%d", &u, &v), make_root(u), a[u].fa = v; 79 for(int i = 1; i <= n; i++) 80 splay(i), scanf("%d", &a[i].val), push_up(i); 81 scanf("%d", &q); 82 while(q--) 83 { 84 scanf("%s%d%d", s, &u, &v); 85 if(s[1] == 'H') 86 splay(u), a[u].val = v, push_up(u); 87 if(s[1] == 'M') 88 { 89 make_root(u), access(v), splay(v); 90 printf("%d\n", a[v].max); 91 } 92 if(s[1] == 'S') 93 { 94 make_root(u), access(v), splay(v); 95 printf("%d\n", a[v].sum); 96 } 97 } 98 return 0; 99 }