[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

Sample Output

4
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 }
View Code
posted @ 2016-05-25 01:01  CtrlCV  阅读(698)  评论(0编辑  收藏  举报