bzoj1036: [ZJOI2008]树的统计Count

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 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

Sample Output

4
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 }
View Code

 

 

树链剖分代码:

  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 }
View Code

 

posted @ 2015-10-23 19:12  yanzx6  阅读(136)  评论(0编辑  收藏  举报