解:有个暴力是枚举两条链然后O(n)判定,可以得到15分。
还可以优化一下,枚举一条链,然后第二条链直接求两端点树上带权距离。可以做到O(m(n + m)),但是我用的树剖,跟上面那一档没啥区别Orz...
然后是链的部分,把所有链按照左端点小到大排序,左端点相同的时候按右端点小到大。
然后从右往左加。用一个树状数组维护前缀最大值。如果一个之前区间的左端点在我们当前区间的右端点内,就有交。
我们漏了一种情况:一个区间被另一个完全包含。于是新开一个树状数组维护即可。注意到这种情况在第一个树状数组中算出的答案不优,会被取代掉。
这样就有30分了。
1 /** 2 * There is no end though there is a start in space. ---Infinity. 3 * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite. 4 * Only the person who was wisdom can read the most foolish one from the history. 5 * The fish that lives in the sea doesn't know the world in the land. 6 * It also ruins and goes if they have wisdom. 7 * It is funnier that man exceeds the speed of light than fish start living in the land. 8 * It can be said that this is an final ultimatum from the god to the people who can fight. 9 * 10 * Steins;Gate 11 */ 12 13 #include <bits/stdc++.h> 14 15 #define forson(x, i) for(int i = e[x]; i; i = edge[i].nex) 16 17 typedef long long LL; 18 const int N = 100010; 19 const LL INF = 9e18; 20 21 struct Edge { 22 int nex, v; 23 LL len; 24 }edge[N << 1]; int tp; 25 26 struct Node { 27 int x, y; 28 LL z, val; 29 inline bool operator < (const Node &w) const { 30 if(x != w.x) return x < w.x; 31 return y < w.y; 32 } 33 }node[N]; 34 35 int n, e[N], m, fa[N], deep[N]; 36 int num, pos[N], son[N], siz[N], top[N]; 37 LL Sum[N], sum[N << 2], d[N], tag[N << 2]; 38 39 inline void add(int x, int y, LL z) { 40 tp++; 41 edge[tp].v = y; 42 edge[tp].len = z; 43 edge[tp].nex = e[x]; 44 e[x] = tp; 45 return; 46 } 47 48 void DFS_1(int x, int f) { /// get fa son siz d deep 49 fa[x] = f; 50 deep[x] = deep[f] + 1; 51 siz[x] = 1; 52 forson(x, i) { 53 int y = edge[i].v; 54 if(y == f) continue; 55 d[y] = d[x] + edge[i].len; 56 DFS_1(y, x); 57 siz[x] += siz[y]; 58 if(siz[y] > siz[son[x]]) { 59 son[x] = y; 60 } 61 } 62 return; 63 } 64 65 void DFS_2(int x, int f) { /// get top id pos 66 pos[x] = ++num; 67 top[x] = f; 68 Sum[num] = d[x] - d[fa[x]]; 69 if(son[x]) { 70 DFS_2(son[x], f); 71 } 72 forson(x, i) { 73 int y = edge[i].v; 74 if(y == fa[x] || y == son[x]) continue; 75 DFS_2(y, y); 76 } 77 return; 78 } 79 80 inline int lca(int x, int y) { 81 while(top[x] != top[y]) { 82 if(deep[top[x]] > deep[top[y]]) { 83 x = fa[top[x]]; 84 } 85 else { 86 y = fa[top[y]]; 87 } 88 } 89 return deep[x] < deep[y] ? x : y; 90 } 91 92 inline LL dis(int x, int y) { 93 return d[x] + d[y] - 2 * d[lca(x, y)]; 94 } 95 96 inline void pushdown(int l, int r, int o) { 97 if(tag[o] != -1) { 98 if(tag[o] == 0) { 99 sum[o << 1] = sum[o << 1 | 1] = 0; 100 } 101 else { 102 int mid = (l + r) >> 1; 103 sum[o << 1] = Sum[mid] - Sum[l - 1]; 104 sum[o << 1 | 1] = Sum[r] - Sum[mid]; 105 } 106 tag[o << 1] = tag[o << 1 | 1] = tag[o]; 107 tag[o] = -1; 108 } 109 return; 110 } 111 112 void Add(int L, int R, int l, int r, int o) { 113 if(L <= l && r <= R) { 114 sum[o] = Sum[r] - Sum[l - 1]; 115 tag[o] = 1; 116 return; 117 } 118 int mid = (l + r) >> 1; 119 pushdown(l, r, o); 120 if(L <= mid) Add(L, R, l, mid, o << 1); 121 if(mid < R) Add(L, R, mid + 1, r, o << 1 | 1); 122 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 123 return; 124 } 125 126 LL ask(int L, int R, int l, int r, int o) { 127 if(L <= l && r <= R) { 128 return sum[o]; 129 } 130 int mid = (l + r) >> 1; 131 pushdown(l, r, o); 132 LL ans = 0; 133 if(L <= mid) { 134 ans += ask(L, R, l, mid, o << 1); 135 } 136 if(mid < R) { 137 ans += ask(L, R, mid + 1, r, o << 1 | 1); 138 } 139 return ans; 140 } 141 142 inline void Add(int x, int y) { 143 while(top[x] != top[y]) { 144 if(deep[top[x]] > deep[top[y]]) { 145 std::swap(x, y); 146 } 147 Add(pos[top[y]], pos[y], 1, n, 1); 148 y = fa[top[y]]; 149 } 150 if(deep[x] > deep[y]) std::swap(x, y); 151 if(x != y) Add(pos[x] + 1, pos[y], 1, n, 1); 152 return; 153 } 154 155 inline LL ask(int x, int y) { 156 LL ans = 0; 157 while(top[x] != top[y]) { 158 if(deep[top[x]] > deep[top[y]]) { 159 std::swap(x, y); 160 } 161 ans += ask(pos[top[y]], pos[y], 1, n, 1); 162 y = fa[top[y]]; 163 } 164 if(deep[x] > deep[y]) std::swap(x, y); 165 if(x != y) ans += ask(pos[x] + 1, pos[y], 1, n, 1); 166 return ans; 167 } 168 169 inline void clear() { 170 memset(e + 1, 0, n * sizeof(int)); 171 memset(son + 1, 0, n * sizeof(int)); 172 tp = 0; 173 num = 0; 174 return; 175 } 176 /* 177 1 178 5 179 1 2 1 180 2 3 3 181 3 4 3 182 1 5 9 183 2 184 1 5 5 185 2 3 8 186 */ 187 188 namespace Line { 189 LL ta[N], ta2[N]; 190 inline LL ask(int i) { 191 LL ans = -INF; 192 for(; i; i -= i & (-i)) { 193 ans = std::max(ans, ta[i]); 194 } 195 return ans; 196 } 197 inline void Add(int i, LL v) { 198 for(; i <= n; i += i & (-i)) { 199 ta[i] = std::max(ta[i], v); 200 } 201 return; 202 } 203 inline LL ask2(int i) { 204 LL ans = -INF; 205 for(; i; i -= i & (-i)) { 206 ans = std::max(ans, ta2[i]); 207 } 208 return ans; 209 } 210 inline void Add2(int i, LL v) { 211 for(; i <= n; i += i & (-i)) { 212 ta2[i] = std::max(ta2[i], v); 213 } 214 return; 215 } 216 inline void solve() { 217 for(int i = 1; i <= n; i++) ta2[i] = ta[i] = -INF; 218 LL ans = -INF; 219 std::sort(node + 1, node + m + 1); 220 for(int i = m; i >= 1; i--) { 221 LL temp = ask(node[i].y - 1); 222 if(temp != -INF) { 223 ans = std::max(ans, temp + node[i].val - Sum[node[i].y]); 224 } 225 temp = ask2(node[i].y); 226 if(temp != -INF) { 227 ans = std::max(ans, temp + node[i].val); 228 } 229 Add(node[i].x, node[i].val + Sum[node[i].x]); 230 Add2(node[i].y, node[i].val + Sum[node[i].x] - Sum[node[i].y]); 231 } 232 if(ans == -INF) puts("F"); 233 else { 234 printf("%lld\n", ans); 235 } 236 clear(); 237 return; 238 } 239 } 240 /* 241 50 242 2 243 1 2 914572059 244 3 245 1 2 213930211 246 1 2 0 247 2 2 0 248 */ 249 inline void solve() { 250 251 sum[1] = tag[1] = 0; 252 253 scanf("%d", &n); 254 LL z; 255 bool FLAG = 1; 256 for(int i = 1, x, y; i < n; i++) { 257 scanf("%d%d%lld", &x, &y, &z); 258 add(x, y, z); 259 add(y, x, z); 260 if(y != x + 1) { 261 FLAG = 0; 262 } 263 } 264 265 DFS_1(1, 0); 266 DFS_2(1, 1); 267 268 for(int i = 1; i <= n; i++) { 269 Sum[i] += Sum[i - 1]; 270 } 271 272 scanf("%d", &m); 273 for(int i = 1; i <= m; i++) { 274 scanf("%d%d%lld", &node[i].x, &node[i].y, &node[i].z); 275 if(node[i].x > node[i].y) std::swap(node[i].x, node[i].y); 276 else if(node[i].x == node[i].y) { 277 m--; 278 i--; 279 } 280 node[i].val = dis(node[i].x, node[i].y) - node[i].z; 281 //printf("node %d [%d %d] val = %lld \n", i, node[i].x, node[i].y, node[i].val); 282 } 283 // solve 284 if(FLAG) { 285 Line::solve(); 286 return; 287 } 288 289 if(m > 300) { 290 clear(); 291 return; 292 } 293 294 LL ans = -INF; 295 for(int i = 1; i < m; i++) { 296 Add(node[i].x, node[i].y); 297 for(int j = i + 1; j <= m; j++) { 298 /// choose i j 299 LL Val = ask(node[j].x, node[j].y); 300 //printf("Val = %lld \n", Val); 301 if(Val) { 302 ans = std::max(ans, node[i].val + node[j].val - Val); 303 } 304 } 305 tag[1] = sum[1] = 0; 306 } 307 if(ans == -INF) { 308 puts("F"); 309 } 310 else { 311 printf("%lld\n", ans); 312 } 313 clear(); 314 return; 315 } 316 317 int main() { 318 319 int T; 320 scanf("%d", &T); 321 while(T--) solve(); 322 return 0; 323 }