Hdu--5052(树链剖分,线段树,*)

2014-10-10 20:24:54

思路:树链剖分是比较好想到的,关键线段树如何实现。线段树每个节点维护五个值:add,tmax(区间最大值),tmin(区间最小值),ans1(向右走最大利润),ans2(向左走最大利润)。然后ans1是由右儿子最大值 - 左儿子最小值得到,ans2反过来。然后在树剖过程中要注意方向性带来的影响。 读入优化了下。

  1 /*************************************************************************
  2     > File Name: 5052.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Fri 10 Oct 2014 07:12:29 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <map>
 14 #include <set>
 15 #include <queue>
 16 #include <iostream>
 17 #include <algorithm>
 18 using namespace std;
 19 #define lp (p << 1)
 20 #define rp (p << 1|1)
 21 #define getmid(l,r) (l + (r - l) / 2)
 22 #define MP(a,b) make_pair(a,b)
 23 typedef long long ll;
 24 const int INF = 1 << 30;
 25 const int maxn = 50010;
 26 
 27 inline int Read(){
 28     int x = 0,f = 1;char c = getchar();
 29     while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
 30     while(c >= '0' && c <= '9'){x = x * 10 + c - '0';c = getchar();}
 31     return x * f;
 32 }
 33 
 34 int T,N,Q;
 35 int first[maxn],next[maxn << 1],ver[maxn << 1],ecnt;
 36 int dep[maxn],sz[maxn],son[maxn],fa[maxn],w[maxn],aw[maxn],top[maxn],tsz;
 37 int val[maxn];
 38 
 39 struct node{
 40     int add;
 41     int tmax,tmin;
 42     int ans1,ans2;
 43 }t[maxn << 2];
 44 
 45 void Add_edge(int u,int v){
 46     next[++ecnt] = first[u];
 47     ver[ecnt] = v;
 48     first[u] = ecnt;
 49 }
 50 
 51 void Dfs(int p,int pre,int d){
 52     sz[p] = 1;
 53     son[p] = -1;
 54     dep[p] = d;
 55     fa[p] = pre;
 56     int v,tmp = 0;
 57     for(int i = first[p]; i != -1; i = next[i]) if((v = ver[i]) != pre){
 58         Dfs(v,p,d + 1);
 59         if(sz[v] > tmp){
 60             tmp = sz[v];
 61             son[p] = v;
 62         }
 63         sz[p] += sz[v];
 64     }
 65 }
 66 
 67 void Dfs_pos(int p,int tp){
 68     w[p] = ++tsz;
 69     aw[tsz] = p;
 70     top[p] = tp;
 71     if(son[p] != -1) Dfs_pos(son[p],tp);
 72     for(int i = first[p]; i != -1; i = next[i]){
 73         int v = ver[i];
 74         if(v != son[p] && v != fa[p])
 75             Dfs_pos(v,v);
 76     }
 77 }
 78 
 79 void Push_up(int p){
 80     t[p].tmax = max(t[lp].tmax,t[rp].tmax);
 81     t[p].tmin = min(t[lp].tmin,t[rp].tmin);
 82 
 83     t[p].ans1 = max(t[lp].ans1,t[rp].ans1);
 84     t[p].ans1 = max(t[p].ans1,t[rp].tmax - t[lp].tmin);
 85 
 86     t[p].ans2 = max(t[lp].ans2,t[rp].ans2);
 87     t[p].ans2 = max(t[p].ans2,t[lp].tmax - t[rp].tmin);
 88 }
 89 
 90 void Push_down(int p){
 91     int c = t[p].add;
 92     if(c){
 93         t[lp].add += c;
 94         t[rp].add += c;
 95         t[lp].tmax += c;
 96         t[lp].tmin += c;
 97         t[rp].tmax += c;
 98         t[rp].tmin += c;
 99         t[p].add = 0;
100     }
101 }
102 
103 void Build_tree(int p,int l,int r){
104     t[p].add = 0;
105     if(l == r){
106         t[p].tmax = t[p].tmin = val[aw[l]];
107         t[p].ans1 = t[p].ans2 = 0;
108         return;
109     }
110     int mid = getmid(l,r);
111     Build_tree(lp,l,mid);
112     Build_tree(rp,mid + 1,r);
113     Push_up(p);
114 }
115 
116 int Query_tree(int f,int a,int b,int p,int l,int r,int & maxx,int & minn){
117     if(a <= l && r <= b){
118         maxx = t[p].tmax;
119         minn = t[p].tmin;
120         if(f == 1) return t[p].ans1;
121         else return t[p].ans2;
122     }
123     int mid = getmid(l,r);
124     Push_down(p);
125     if(b <= mid) return Query_tree(f,a,b,lp,l,mid,maxx,minn);
126     else if(a > mid) return Query_tree(f,a,b,rp,mid + 1,r,maxx,minn);
127     else{
128         int maxl,maxr,minl,minr;
129         int res = max(Query_tree(f,a,b,lp,l,mid,maxl,minl),
130                 Query_tree(f,a,b,rp,mid + 1,r,maxr,minr));
131         maxx = max(maxl,maxr);
132         minn = min(minl,minr);
133         if(f == 1) return max(res,maxr - minl);
134         else return max(res,maxl - minr);
135     }
136 }
137 
138 int Find(int a,int b){
139     int f1 = top[a],f2 = top[b],maxl,maxr,minl,minr,tmax,tmin;
140     maxl = maxr = -INF;
141     minl = minr = INF;
142     int res = -INF;
143     while(f1 != f2){
144         if(dep[f1] > dep[f2]){
145             res = max(res,Query_tree(2,w[f1],w[a],1,1,tsz,tmax,tmin));
146             res = max(res,tmax - minl);
147             maxl = max(maxl,tmax);
148             minl = min(minl,tmin);
149             a = fa[f1];
150             f1 = top[a];
151         }
152         else{
153             res = max(res,Query_tree(1,w[f2],w[b],1,1,tsz,tmax,tmin));
154             res = max(res,maxr - tmin);
155             maxr = max(maxr,tmax);
156             minr = min(minr,tmin);
157             b = fa[f2];
158             f2 = top[b];
159         }
160     }
161     if(dep[a] > dep[b])
162         res = max(res,Query_tree(2,w[b],w[a],1,1,tsz,tmax,tmin));
163     else
164         res = max(res,Query_tree(1,w[a],w[b],1,1,tsz,tmax,tmin));
165     res = max(res,tmax - minl);
166     res = max(res,maxr - tmin);
167     res = max(res,maxr - minl);
168     return res;
169 }
170 
171 void Update_tree(int a,int b,int c,int p,int l,int r){
172     if(a <= l && r <= b){
173         t[p].add += c;
174         t[p].tmax += c;
175         t[p].tmin += c;
176         return;
177     }
178     Push_down(p);
179     int mid = getmid(l,r);
180     if(a <= mid) Update_tree(a,b,c,lp,l,mid);
181     if(b > mid) Update_tree(a,b,c,rp,mid + 1,r);
182     Push_up(p);
183 }
184 
185 void Change(int a,int b,int c){
186     int f1 = top[a],f2 = top[b];
187     while(f1 != f2){
188         if(dep[f1] > dep[f2]){
189             swap(a,b);
190             swap(f1,f2);
191         }
192         Update_tree(w[f2],w[b],c,1,1,tsz);
193         b = fa[f2];
194         f2 = top[b];
195     }
196     if(dep[a] > dep[b]) swap(a,b);
197     Update_tree(w[a],w[b],c,1,1,tsz);
198 }
199 
200 int main(){
201     int a,b,c;
202     T = Read();
203     while(T--){
204         memset(first,-1,sizeof(first));
205         ecnt = tsz = 0;
206         N = Read();
207         for(int i = 1; i <= N; ++i)
208             val[i] = Read();
209         for(int i = 1; i < N; ++i){
210             a = Read(),b = Read();
211             Add_edge(a,b);
212             Add_edge(b,a);
213         }
214         Dfs(1,0,0);
215         Dfs_pos(1,1);
216         Build_tree(1,1,tsz);
217         Q = Read();
218         for(int i = 1; i <= Q; ++i){
219             a = Read(),b = Read(),c = Read();
220             int ans = Find(a,b);
221             if(ans < 0) ans = 0;
222             printf("%d\n",ans);
223             Change(a,b,c);
224         }
225     }
226     return 0;
227 }

 

posted @ 2014-10-10 20:28  Naturain  阅读(228)  评论(0编辑  收藏  举报