// NOI2018 情报中心 (duck.ac noi18e) — optimized
// segment-tree merge (case 1) + virtual tree / diameter merge (case 2).
// O(1) LCA (Euler tour + sparse table). Iterative traversals.
#include <bits/stdc++.h>
#include <stdint.h>
using namespace std;
typedef long long ll;
static char FI[1 << 20], *FA = FI, *FB = FI;
static inline int gc() {
if (FA == FB) { FB = (FA = FI) + fread(FI, 1, sizeof(FI), stdin); if (FA == FB) return EOF; }
return (unsigned char)*FA++;
}
static inline ll rd() {
int c = gc();
while (c != EOF && (c < '0' || c > '9')) c = gc();
ll x = 0;
while (c >= '0' && c <= '9') { x = x * 10 + (c - '0'); c = gc(); }
return x;
}
const int MAXN = 50005;
const int MAXM = 100005;
const int LG2 = 17; // ceil(log2(2*MAXN))
const ll NEG = -(1LL << 60);
const ll ANS_INIT = -(1LL << 59);
int n, m;
ll ans;
// ---------- Tree ----------
int head[MAXN], ecnt;
struct Edge { int to, nxt; ll w; } edge[MAXN * 2 + 5];
inline void addEdge(int u, int v, ll w) { edge[++ecnt] = {v, head[u], w}; head[u] = ecnt; }
int par[MAXN], dep[MAXN];
ll D[MAXN];
int tin[MAXN], tout[MAXN];
int ord[MAXN], ordcnt;
int stk_[MAXN], stk_top;
int maxd;
// Euler tour + sparse table for O(1) LCA
int et[MAXN * 2 + 5], det[MAXN * 2 + 5], et_cnt;
int first[MAXN];
int st[LG2][MAXN * 2 + 5];
void buildTree() {
par[1] = 0; dep[1] = 0; D[1] = 0;
ordcnt = 0; stk_top = 1; stk_[1] = 1;
while (stk_top) {
int x = stk_[stk_top--];
ord[++ordcnt] = x;
tin[x] = ordcnt;
for (int ei = head[x]; ei; ei = edge[ei].nxt) {
int v = edge[ei].to;
if (v == par[x]) continue;
par[v] = x;
dep[v] = dep[x] + 1;
D[v] = D[x] + edge[ei].w;
stk_[++stk_top] = v;
}
}
maxd = 0;
for (int i = 1; i <= n; ++i) { if (dep[i] > maxd) maxd = dep[i]; tout[ord[i]] = tin[ord[i]]; }
for (int i = n; i >= 2; --i) {
int x = ord[i], p = par[x];
if (tout[x] > tout[p]) tout[p] = tout[x];
}
}
void buildEuler() {
et_cnt = 0;
int sn[MAXN], se[MAXN]; int top = 1;
sn[1] = 1; se[1] = head[1];
first[1] = et_cnt; et[et_cnt] = 1; det[et_cnt] = 0; et_cnt++;
while (top) {
int x = sn[top];
int ei = se[top];
while (ei && edge[ei].to == par[x]) ei = edge[ei].nxt;
if (ei) {
int v = edge[ei].to;
se[top] = edge[ei].nxt;
first[v] = et_cnt;
et[et_cnt] = v; det[et_cnt] = dep[v]; et_cnt++;
sn[++top] = v; se[top] = head[v];
} else {
top--;
if (top) { et[et_cnt] = sn[top]; det[et_cnt] = dep[sn[top]]; et_cnt++; }
}
}
for (int i = 0; i < et_cnt; ++i) st[0][i] = i;
for (int k = 1; (1 << k) <= et_cnt; ++k)
for (int i = 0; i + (1 << k) <= et_cnt; ++i) {
int a = st[k - 1][i], b = st[k - 1][i + (1 << (k - 1))];
st[k][i] = (det[a] <= det[b]) ? a : b;
}
}
inline int lca(int x, int y) {
int l = first[x], r = first[y];
if (l > r) { int t = l; l = r; r = t; }
int k = 31 - __builtin_clz((unsigned)(r - l + 1));
int a = st[k][l], b = st[k][r - (1 << k) + 1];
return det[a] <= det[b] ? et[a] : et[b];
}
// ---------- Queries ----------
struct Query { int x, y; ll v; } q[MAXM + 5];
struct Chain { int nxt, d; ll v1, v2; };
Chain ch[MAXM * 2 + 5];
int ch_head[MAXN], ch_cnt;
inline void addChain(int node, int d, ll v1, ll v2) {
ch[++ch_cnt] = {ch_head[node], d, v1, v2};
ch_head[node] = ch_cnt;
}
struct PathNode { int nxt, idx; };
PathNode pn[MAXM + 5];
int pn_head[MAXN], pn_cnt;
inline void addPath(int node, int idx) {
pn[++pn_cnt] = {pn_head[node], idx};
pn_head[node] = pn_cnt;
}
// ---------- Segment tree merge (case 1) ----------
struct SegNode { ll V1, V2; int ch[2]; };
static SegNode seg[4000000];
static int reuse[4000000];
int seg_tot, reuse_tot;
inline int newNode() {
if (reuse_tot) {
int id = reuse[--reuse_tot];
seg[id].V1 = seg[id].V2 = NEG; seg[id].ch[0] = seg[id].ch[1] = 0;
return id;
}
++seg_tot;
seg[seg_tot].V1 = seg[seg_tot].V2 = NEG; seg[seg_tot].ch[0] = seg[seg_tot].ch[1] = 0;
return seg_tot;
}
void segInsert(int &rt, int pos, ll v1, ll v2, int l, int r) {
if (!rt) rt = newNode();
if (l == r) {
if (v1 > seg[rt].V1) seg[rt].V1 = v1;
if (v2 > seg[rt].V2) seg[rt].V2 = v2;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) segInsert(seg[rt].ch[0], pos, v1, v2, l, mid);
else segInsert(seg[rt].ch[1], pos, v1, v2, mid + 1, r);
seg[rt].V1 = max(seg[seg[rt].ch[0]].V1, seg[seg[rt].ch[1]].V1);
seg[rt].V2 = max(seg[seg[rt].ch[0]].V2, seg[seg[rt].ch[1]].V2);
}
void segErase(int &rt, int pos, int l, int r) {
if (!rt) return;
if (l == r) { reuse[reuse_tot++] = rt; rt = 0; return; }
int mid = (l + r) >> 1;
if (pos <= mid) segErase(seg[rt].ch[0], pos, l, mid);
else segErase(seg[rt].ch[1], pos, mid + 1, r);
if (!seg[rt].ch[0] && !seg[rt].ch[1]) { reuse[reuse_tot++] = rt; rt = 0; }
else {
seg[rt].V1 = max(seg[seg[rt].ch[0]].V1, seg[seg[rt].ch[1]].V1);
seg[rt].V2 = max(seg[seg[rt].ch[0]].V2, seg[seg[rt].ch[1]].V2);
}
}
void segMerge(int &x, int y, ll &t, int l, int r) {
if (!y) return;
if (!x) { x = y; return; }
int xl = seg[x].ch[0], xr = seg[x].ch[1];
int yl = seg[y].ch[0], yr = seg[y].ch[1];
if (l == r) {
if (seg[y].V1 > seg[x].V1) seg[x].V1 = seg[y].V1;
if (seg[y].V2 > seg[x].V2) seg[x].V2 = seg[y].V2;
reuse[reuse_tot++] = y;
return;
}
ll tmp = seg[xl].V2 + seg[yr].V1;
if (tmp > t) t = tmp;
tmp = seg[xr].V1 + seg[yl].V2;
if (tmp > t) t = tmp;
reuse[reuse_tot++] = y;
int mid = (l + r) >> 1;
segMerge(xl, yl, t, l, mid);
segMerge(xr, yr, t, mid + 1, r);
seg[x].ch[0] = xl; seg[x].ch[1] = xr;
ll v1 = seg[xl].V1, v2 = seg[xl].V2;
if (seg[xr].V1 > v1) v1 = seg[xr].V1;
if (seg[xr].V2 > v2) v2 = seg[xr].V2;
seg[x].V1 = v1; seg[x].V2 = v2;
}
int Rt[MAXN];
void solveT() {
for (int idx = n; idx >= 1; --idx) {
int x = ord[idx];
Rt[x] = 0;
ll t = NEG;
for (int ei = head[x]; ei; ei = edge[ei].nxt) {
int v = edge[ei].to;
if (v == par[x]) continue;
segMerge(Rt[x], Rt[v], t, 0, maxd);
}
for (int ci = ch_head[x]; ci; ci = ch[ci].nxt) {
int rt = 0;
segInsert(rt, ch[ci].d, ch[ci].v1, ch[ci].v2, 0, maxd);
segMerge(Rt[x], rt, t, 0, maxd);
}
ll cand = t - D[x];
if (cand > ans) ans = cand;
if (dep[x] > 0) segErase(Rt[x], dep[x] - 1, 0, maxd);
}
}
// ---------- Virtual tree + diameter merge (case 2) ----------
int o[MAXM * 4 + 10];
int nf[MAXM * 2 + 10]; ll nD[MAXM * 2 + 10];
int whead[MAXN], wnext[MAXM * 2 + 10];
int vis[MAXN];
int anc[MAXM * 4], vstk[MAXM * 4], px[MAXM * 4], py[MAXM * 4];
ll tt[MAXM * 4];
inline bool cmpDfn(int a, int b) { return tin[a] < tin[b]; }
inline ll disAP(int x, int y) {
if (!x || !y) return NEG;
return nD[x] + nD[y] - 2 * D[lca(nf[x], nf[y])];
}
inline void mergeDiam(int &x, int &y, int a, int b, ll &t) {
ll d1 = disAP(x, a), d2 = disAP(x, b), d3 = disAP(y, a), d4 = disAP(y, b);
if (d1 > t) t = d1;
if (d2 > t) t = d2;
if (d3 > t) t = d3;
if (d4 > t) t = d4;
ll p1 = disAP(x, y), p2 = disAP(a, b);
if (p2 >= p1 && p2 >= d1 && p2 >= d2 && p2 >= d3 && p2 >= d4) { x = a; y = b; return; }
if (p1 >= d1 && p1 >= d2 && p1 >= d3 && p1 >= d4) return;
if (d1 >= d2 && d1 >= d3 && d1 >= d4) y = a;
else if (d2 >= d3 && d2 >= d4) y = b;
else if (d3 >= d4) x = a;
else x = b;
}
void vtree(int *o, int c) {
sort(o + 1, o + c + 1, cmpDfn);
int nc = 0;
for (int i = 1; i <= c; ++i) if (i == 1 || o[i] != o[i - 1]) o[++nc] = o[i];
c = nc;
for (int i = 1; i <= c; ++i) vis[o[i]] = 1;
for (int i = 1; i < c; ++i) {
int k = lca(o[i], o[i + 1]);
if (!vis[k]) { vis[k] = 1; o[++nc] = k; }
}
sort(o + 1, o + nc + 1, cmpDfn);
c = 0;
for (int i = 1; i <= nc; ++i) if (i == 1 || o[i] != o[i - 1]) o[++c] = o[i];
int T = 0;
vstk[++T] = 1;
for (int i = 2; i <= c; ++i) {
while (tout[o[vstk[T]]] < tin[o[i]]) --T;
anc[i] = vstk[T];
vstk[++T] = i;
}
for (int i = 1; i <= c; ++i) { tt[i] = NEG; px[i] = 0; py[i] = 0; }
for (int i = c; i > 1; --i) {
for (int j = whead[o[i]]; j; j = wnext[j]) mergeDiam(px[i], py[i], j, 0, tt[i]);
ll cand = (tt[i] - 2 * D[o[i]]) >> 1;
if (cand > ans) ans = cand;
mergeDiam(px[anc[i]], py[anc[i]], px[i], py[i], tt[anc[i]]);
}
for (int i = 1; i <= c; ++i) {
vis[o[i]] = 0; anc[i] = 0; px[i] = 0; py[i] = 0; tt[i] = 0;
whead[o[i]] = 0;
}
}
void solveV() {
for (int x = 1; x <= n; ++x) {
if (!pn_head[x]) continue;
int c = 0;
for (int pi = pn_head[x]; pi; pi = pn[pi].nxt) {
int idx = pn[pi].idx;
int qx = q[idx].x, qy = q[idx].y;
ll val = 2 * (D[qx] + D[qy] - D[x] - q[idx].v);
++c; o[c] = qx; nf[c] = qy; nD[c] = val;
wnext[c] = whead[qx]; whead[qx] = c;
++c; o[c] = qy; nf[c] = qx; nD[c] = val;
wnext[c] = whead[qy]; whead[qy] = c;
}
vtree(o, c);
pn_head[x] = 0;
}
}
// ---------- Main ----------
int main() {
seg[0].V1 = seg[0].V2 = NEG; seg[0].ch[0] = seg[0].ch[1] = 0;
seg_tot = 0; reuse_tot = 0;
int T = (int)rd();
while (T--) {
n = (int)rd();
ecnt = 0;
for (int i = 1; i <= n; ++i) { head[i] = 0; ch_head[i] = 0; pn_head[i] = 0; par[i] = 0; }
for (int i = 1; i < n; ++i) {
int a = (int)rd(), b = (int)rd(); ll c = rd();
addEdge(a, b, c); addEdge(b, a, c);
}
buildTree();
buildEuler();
m = (int)rd();
ch_cnt = 0; pn_cnt = 0;
for (int i = 1; i <= m; ++i) {
int x = (int)rd(), y = (int)rd(); ll v = rd();
q[i] = {x, y, v};
int z = lca(x, y);
addPath(z, i);
if (x != z) addChain(x, dep[z], D[x] + D[y] - D[z] - v, D[x] + D[y] - 2 * D[z] - v);
if (y != z) addChain(y, dep[z], D[x] + D[y] - D[z] - v, D[x] + D[y] - 2 * D[z] - v);
}
ans = ANS_INIT;
solveT();
solveV();
if (ans == ANS_INIT) puts("F");
else printf("%lld\n", ans);
}
return 0;
}
| Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
| Testcase #1 | 118.12 us | 564 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #2 | 355.62 us | 596 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #3 | 3.521 ms | 1020 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #4 | 36.53 ms | 1 MB + 904 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #5 | 697.656 ms | 5 MB + 540 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #6 | 1.298 s | 19 MB + 104 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #7 | 374.515 ms | 5 MB + 540 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #8 | 687.08 ms | 18 MB + 600 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #9 | 700.158 ms | 17 MB + 976 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #10 | 159.66 ms | 4 MB + 112 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #11 | 350.605 ms | 14 MB + 952 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #12 | 357.568 ms | 14 MB + 764 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #13 | 570.445 ms | 6 MB + 920 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #14 | 569.683 ms | 7 MB + 112 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #15 | 846.073 ms | 24 MB + 108 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #16 | 779.239 ms | 24 MB + 1000 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #17 | 363.795 ms | 5 MB + 480 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #18 | 672.674 ms | 18 MB + 372 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #19 | 585.506 ms | 18 MB + 460 KB | Accepted | Score: 5 | 显示更多 |
| Testcase #20 | 572.356 ms | 18 MB + 216 KB | Accepted | Score: 5 | 显示更多 |