bzoj1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 9113 Solved: 3695
[Submit][Status][Discuss]
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
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
分析:很简单的一道题,块状树、动态树、树链剖分、主席树等等等等
我只写了动态树和树链剖分
动态树就是把链用Splay的形式存起来,利用Splay的特点,然后用左孩子表示此点上面的点,右孩子表示下面的点
树链剖分就是用线段树维护一条条重链,实现时维护一个类似于dfs序列的东西,然后在这个上面建个线段树。
动态树代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <deque> 6 #include <vector> 7 #include <queue> 8 #include <iostream> 9 #include <algorithm> 10 #include <map> 11 #include <set> 12 #include <ctime> 13 using namespace std; 14 typedef long long LL; 15 typedef double DB; 16 #define For(i, s, t) for(int i = (s); i <= (t); i++) 17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--) 18 #define Rep(i, t) for(int i = (0); i < (t); i++) 19 #define Repn(i, t) for(int i = ((t)-1); i >= (0); i--) 20 #define rep(i, x, t) for(int i = (x); i < (t); i++) 21 #define MIT (2147483647) 22 #define INF (1000000001) 23 #define MLL (1000000000000000001LL) 24 #define sz(x) ((int) (x).size()) 25 #define clr(x, y) memset(x, y, sizeof(x)) 26 #define puf push_front 27 #define pub push_back 28 #define pof pop_front 29 #define pob pop_back 30 #define ft first 31 #define sd second 32 #define mk make_pair 33 inline void SetIO(string Name) { 34 string Input = Name+".in", 35 Output = Name+".out"; 36 freopen(Input.c_str(), "r", stdin), 37 freopen(Output.c_str(), "w", stdout); 38 } 39 40 inline int Getint() { 41 int Ret = 0; 42 char Ch = ' '; 43 bool Flag = 0; 44 while(!(Ch >= '0' && Ch <= '9')) { 45 if(Ch == '-') Flag ^= 1; 46 Ch = getchar(); 47 } 48 while(Ch >= '0' && Ch <= '9') { 49 Ret = Ret*10+Ch-'0'; 50 Ch = getchar(); 51 } 52 return Flag ? -Ret : Ret; 53 } 54 55 const int N = 30010; 56 int n, m, Arr[N]; 57 int First[N], To[N*2], Next[N*2], Edges; 58 struct SplayType { 59 int Child[2], Fa, Max, Sum, Val; 60 #define Lc(x) (Tr[x].Child[0]) 61 #define Rc(x) (Tr[x].Child[1]) 62 #define Child(x, y) (Tr[x].Child[y]) 63 #define Fa(x) (Tr[x].Fa) 64 #define Max(x) (Tr[x].Max) 65 #define Sum(x) (Tr[x].Sum) 66 #define Val(x) (Tr[x].Val) 67 } Tr[N]; 68 69 inline void Insert(int u, int v) { 70 Edges++; 71 To[Edges] = v, Next[Edges] = First[u]; 72 First[u] = Edges; 73 } 74 75 inline void Input() { 76 n = Getint(); 77 For(i, 1, n-1) { 78 int a = Getint(); 79 int b = Getint(); 80 Insert(a, b), Insert(b, a); 81 } 82 For(i, 1, n) Arr[i] = Getint(); 83 } 84 85 inline void Bfs() { 86 static int Que[N]; 87 int Head = 1, Tail = 1; 88 Que[1] = 1, Fa(1) = 0; 89 while(Head <= Tail) { 90 int u = Que[Head++]; 91 for(int Tab = First[u], v; Tab; Tab = Next[Tab]) 92 if(!Fa(v = To[Tab]) && v != 1) Fa(v) = u, Que[++Tail] = v; 93 } 94 } 95 96 inline bool Root(int x) { 97 return Lc(Fa(x)) != x && Rc(Fa(x)) != x; 98 } 99 100 inline void Updata(int x) { 101 Sum(x) = Max(x) = Val(x); 102 Rep(i, 2) 103 Sum(x) += Sum(Child(x, i)), 104 Max(x) = max(Max(x), Max(Child(x, i))); 105 } 106 107 inline void Rotate(int x, bool T) { 108 int y = Fa(x); 109 int z = Fa(y); 110 if(Lc(z) == y) Lc(z) = x; 111 else if(Rc(z) == y) Rc(z) = x; 112 Fa(x) = z; 113 Child(y, !T) = Child(x, T); 114 if(Child(x, T)) Fa(Child(x, T)) = y; 115 Child(x, T) = y, Fa(y) = x; 116 Updata(y); 117 } 118 119 inline void Splay(int x) { 120 int y, z; 121 bool T1, T2; 122 while(!Root(x)) { 123 y = Fa(x); 124 z = Fa(y); 125 T1 = Lc(y) == x, T2 = Lc(z) == y; 126 if(Root(y)) Rotate(x, T1); 127 else if(T1^T2) Rotate(x, T1), Rotate(x, T2); 128 else Rotate(y, T2), Rotate(x, T1); 129 } 130 Updata(x); 131 } 132 133 inline void Expose(int u) { 134 int v = 0; 135 while(u) { 136 Splay(u); 137 Rc(u) = v; 138 Updata(u); 139 v = u; 140 u = Fa(u); 141 } 142 } 143 144 inline void Work(int x, int y, int Type) { 145 Expose(y); 146 y = 0; 147 while(1) { 148 Splay(x); 149 150 if(!Fa(x)) { 151 if(Type) printf("%d\n", Sum(y)+Val(x)+Sum(Rc(x))); 152 else printf("%d\n", max(Max(y), max(Val(x), Max(Rc(x))))); 153 break; 154 } 155 156 Rc(x) = y; 157 Updata(x); 158 y = x; 159 x = Fa(x); 160 } 161 } 162 163 inline void Change(int x, int v) { 164 Splay(x); 165 Val(x) = v; 166 Updata(x); 167 } 168 169 inline void Solve() { 170 Bfs(); 171 For(i, 1, n) Sum(i) = Max(i) = Val(i) = Arr[i]; 172 Sum(0) = 0, Max(0) = Val(0) = -INF; 173 174 m = Getint(); 175 while(m--) { 176 char Opt = ' '; 177 while(Opt != 'Q' && Opt != 'C') Opt = getchar(); 178 Opt = getchar(); 179 int x = Getint(); 180 int y = Getint(); 181 if(Opt == 'M' || Opt == 'S') Work(x, y, Opt == 'S'); 182 else Change(x, y); 183 } 184 } 185 186 int main() { 187 #ifndef ONLINE_JUDGE 188 SetIO("1036"); 189 #endif 190 Input(); 191 Solve(); 192 return 0; 193 }
树链剖分代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <deque> 6 #include <vector> 7 #include <queue> 8 #include <iostream> 9 #include <algorithm> 10 #include <map> 11 #include <set> 12 #include <ctime> 13 using namespace std; 14 typedef long long LL; 15 typedef double DB; 16 #define For(i, s, t) for(int i = (s); i <= (t); i++) 17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--) 18 #define Rep(i, t) for(int i = (0); i < (t); i++) 19 #define Repn(i, t) for(int i = ((t)-1); i >= (0); i--) 20 #define rep(i, x, t) for(int i = (x); i < (t); i++) 21 #define MIT (2147483647) 22 #define INF (1000000001) 23 #define MLL (1000000000000000001LL) 24 #define sz(x) ((int) (x).size()) 25 #define clr(x, y) memset(x, y, sizeof(x)) 26 #define puf push_front 27 #define pub push_back 28 #define pof pop_front 29 #define pob pop_back 30 #define ft first 31 #define sd second 32 #define mk make_pair 33 inline void SetIO(string Name) { 34 string Input = Name+".in", 35 Output = Name+".out"; 36 freopen(Input.c_str(), "r", stdin), 37 freopen(Output.c_str(), "w", stdout); 38 } 39 40 inline int Getint() { 41 int Ret = 0; 42 char Ch = ' '; 43 bool Flag = 0; 44 while(!(Ch >= '0' && Ch <= '9')) { 45 if(Ch == '-') Flag ^= 1; 46 Ch = getchar(); 47 } 48 while(Ch >= '0' && Ch <= '9') { 49 Ret = Ret*10+Ch-'0'; 50 Ch = getchar(); 51 } 52 return Flag ? -Ret : Ret; 53 } 54 55 const int N = 30010, M = 16; 56 int n, m, Arr[N]; 57 int First[N], To[N*2], Next[N*2], Edges; 58 int Que[N], Len, Size[N], Son[N]; 59 int Dep[N], Fa[N], Index[N], Root[N], Who[N]; 60 struct SegType { 61 int Max, Sum, Child[2]; 62 #define Max(x) (Seg[x].Max) 63 #define Sum(x) (Seg[x].Sum) 64 #define Child(x, y) (Seg[x].Child[y]) 65 #define Lc(x) (Seg[x].Child[0]) 66 #define Rc(x) (Seg[x].Child[1]) 67 } Seg[N*M]; 68 int Tot; 69 70 inline void Insert(int u, int v) { 71 Edges++; 72 To[Edges] = v, Next[Edges] = First[u]; 73 First[u] = Edges; 74 } 75 76 inline void Input() { 77 n = Getint(); 78 For(i, 1, n-1) { 79 int x = Getint(); 80 int y = Getint(); 81 Insert(x, y), Insert(y, x); 82 } 83 For(i, 1, n) Arr[i] = Getint(); 84 } 85 86 inline void Bfs() { 87 int Head = 1, Tail = 1; 88 Que[1] = 1, Dep[1] = 1; 89 while(Head <= Tail) { 90 int u = Que[Head++]; 91 for(int Tab = First[u], v; Tab; Tab = Next[Tab]) 92 if(!Dep[v = To[Tab]]) { 93 Dep[v] = Dep[u]+1, Fa[v] = u; 94 Que[++Tail] = v; 95 } 96 } 97 98 Ford(i, n, 1) { 99 int x = Que[i]; 100 Size[x]++; 101 if(Fa[x]) { 102 Size[Fa[x]] += Size[x]; 103 if(Size[Son[Fa[x]]] < Size[x]) 104 Son[Fa[x]] = x; 105 } 106 } 107 108 Index[1] = 1, Root[1] = 1; 109 For(i, 1, n) { 110 int x = Que[i]; 111 if(!Son[x]) continue; 112 Index[Son[x]] = Index[x]+1, Root[Son[x]] = Root[x]; 113 int Cnt = Index[x]+Size[Son[x]]; 114 for(int Tab = First[x], v; Tab; Tab = Next[Tab]) { 115 v = To[Tab]; 116 if(v != Son[x] && v != Fa[x]) { 117 Index[v] = Cnt+1, Root[v] = v; 118 Cnt += Size[v]; 119 } 120 } 121 } 122 For(i, 1, n) Who[Index[i]] = i; 123 } 124 125 inline void Updata(int x) { 126 Max(x) = -INF, Sum(x) = 0; 127 Rep(i, 2) 128 Max(x) = max(Max(x), Max(Child(x, i))), 129 Sum(x) += Sum(Child(x, i)); 130 } 131 132 inline int Build(int Left, int Right) { 133 int x = ++Tot, Mid = (Left+Right)>>1; 134 if(Left == Right) Max(x) = Sum(x) = Arr[Who[Left]]; 135 else { 136 Lc(x) = Build(Left, Mid); 137 Rc(x) = Build(Mid+1, Right); 138 Updata(x); 139 } 140 return x; 141 } 142 143 inline void Calc(int &Ret, int Tmp, int Type) { 144 if(Type) Ret += Tmp; 145 else Ret = max(Ret, Tmp); 146 } 147 148 inline int Query(int x, int L, int R, int Left, int Right, int Type) { 149 int Ret = Type ? 0 : -INF; 150 if(L >= Left && R <= Right) 151 Calc(Ret, Type ? Sum(x) : Max(x), Type); 152 else { 153 int Mid = (L+R)>>1, Tmp; 154 if(Right <= Mid) 155 Ret = Query(Lc(x), L, Mid, Left, Right, Type); 156 else if(Left > Mid) 157 Ret = Query(Rc(x), Mid+1, R, Left, Right, Type); 158 else { 159 Tmp = Query(Lc(x), L, Mid, Left, Mid, Type); 160 Calc(Ret, Tmp, Type); 161 Tmp = Query(Rc(x), Mid+1, R, Mid+1, Right, Type); 162 Calc(Ret, Tmp, Type); 163 } 164 } 165 return Ret; 166 } 167 168 inline void Change(int x, int L, int R, int k, int v) { 169 if(L == R) Sum(x) = Max(x) = v; 170 else { 171 int Mid = (L+R)>>1; 172 if(k <= Mid) Change(Lc(x), L, Mid, k, v); 173 else Change(Rc(x), Mid+1, R, k, v); 174 Updata(x); 175 } 176 } 177 178 inline void Work(int x, int y, int Type) { 179 int Ret = Type ? 0 : -INF, Tmp; 180 while(Root[x] != Root[y]) { 181 if(Dep[Root[x]] < Dep[Root[y]]) swap(x, y); 182 Tmp = Query(1, 1, n, Index[Root[x]], Index[x], Type); 183 Calc(Ret, Tmp, Type); 184 x = Fa[Root[x]]; 185 } 186 if(Index[x] > Index[y]) swap(x, y); 187 Tmp = Query(1, 1, n, Index[x], Index[y], Type); 188 Calc(Ret, Tmp, Type); 189 190 printf("%d\n", Ret); 191 } 192 193 inline void Solve() { 194 Bfs(); 195 Build(1, n); 196 197 m = Getint(); 198 while(m--) { 199 char Opt = ' '; 200 while(Opt != 'Q' && Opt != 'C') Opt = getchar(); 201 Opt = getchar(); 202 int x = Getint(); 203 int y = Getint(); 204 if(Opt == 'M') Work(x, y, 0); 205 else if(Opt == 'S') Work(x, y, 1); 206 else Change(1, 1, n, Index[x], y); 207 } 208 } 209 210 int main() { 211 #ifndef ONLINE_JUDGE 212 SetIO("1036"); 213 #endif 214 Input(); 215 Solve(); 216 return 0; 217 }