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 }