voidbuild(int u, int L, int R){ if (L == R) return prod[u] = { g[pos[L]][0], g[pos[L]][0], g[pos[L]][1], -INF, }, void(); build(u<<1, L, Mid), build(u<<1|1, Mid+1, R); pushup(u); }
Matrix query(int u, int l, int r, int L, int R){ if (l <= L && R <= r) return prod[u]; if (l > Mid) returnquery(u<<1|1, l, r, Mid+1, R); if (Mid+1 > r) returnquery(u<<1, l, r, L, Mid); returnquery(u<<1, l, r, L, Mid) * query(u<<1|1, l, r, Mid+1, R); }
voidmodify(int u, int p, int L, int R){ if (L == R) return prod[u] = { g[pos[L]][0], g[pos[L]][0], g[pos[L]][1], -INF, }, void(); if (p <= Mid) modify(u<<1, p, L, Mid); elsemodify(u<<1|1, p, Mid+1, R); pushup(u); }
voidupdate(int u, int k){ g[u][1] += k - w[u]; w[u] = k;
while (u) { int tp = top[u]; modify(1, dfn[u], 1, n); Matrix mat = query(1, dfn[tp], dfn[ed[tp]], 1, n); int f0 = max(mat.dat[0][0], mat.dat[0][1]); int f1 = max(mat.dat[1][0], mat.dat[1][1]);
voiddfs1(int u, int f){ sz[u] = 1, fa[u] = f; for (int i = h[u]; i; i = e[i].nxt) { int to = e[i].to; if (to == f) continue; dfs1(to, u); sz[u] += sz[to]; if (sz[son[u]] < sz[to]) son[u] = to; } }
voiddfs2(int u, int t){ top[u] = t, dfn[u] = ++ts, pos[ts] = u; if (!son[u]) return ed[t] = u, void(); dfs2(son[u], t); for (int i = h[u]; i; i = e[i].nxt) { int to = e[i].to; if (to == fa[u] || to == son[u]) continue; dfs2(to, to); } }
voiddfs3(int u){ g[u][0] = 0, g[u][1] = w[u];
for (int i = h[u]; i; i = e[i].nxt) { int to = e[i].to; if (to == fa[u]) continue; dfs3(to); if (to != son[u]) { g[u][0] += max(f[to][0], f[to][1]); g[u][1] += f[to][0]; } }
intmain(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &w[i]); for (int i = 1, a, b; i < n; i++) scanf("%d%d", &a, &b), add(a, b), add(b, a); dfs1(1, 0); dfs2(1, 1); dfs3(1); build(1, 1, n);
for (int i = 1, a, k; i <= m; i++) { scanf("%d%d", &a, &k); update(a, k); printf("%d\n", max(f[1][0], f[1][1])); }
return0; }
[NOIP2018] 保卫王国
Z 国有 n 座城市,(n−1) 条双向道路,每条双向道路连接两座城市,且任意两座城市都能通过若干条道路相互到达。
Z 国的国防部长小 Z 要在城市中驻扎军队。驻扎军队需要满足如下几个条件:
一座城市可以驻扎一支军队,也可以不驻扎军队。
由道路直接连接的两座城市中至少要有一座城市驻扎军队。
在城市里驻扎军队会产生花费,在编号为 i 的城市中驻扎军队的花费是 pi。
小 Z 很快就规划出了一种驻扎军队的方案,使总花费最小。但是国王又给小 Z 提出了 m 个要求,每个要求规定了其中两座城市是否驻扎军队。小 Z 需要针对每个要求逐一给出回答。具体而言,如果国王提出的第 j 个要求能够满足上述驻扎条件(不需要考虑第 j 个要求之外的其它要求),则需要给出在此要求前提下驻扎军队的最小开销。如果国王提出的第 j 个要求无法满足,则需要输出 −1。现在请你来帮助小 Z。
#define int long long #define Mid ((L+R) >> 1) constint N = 100010, INF = 1e17; int n, m, p[N], h[N], f[N][2], g[N][2], idx = 2; int dfn[N], pos[N], son[N], sz[N], fa[N], top[N], ed[N], ts; structEdge { int to, nxt; } e[N<<1];
voidadd(int a, int b){ e[idx] = {b, h[a]}, h[a] = idx++; }
voidbuild(int u, int L, int R){ if (L == R) return prod[u] = { INF, g[pos[L]][0], g[pos[L]][1], g[pos[L]][1], }, void(); build(u<<1, L, Mid), build(u<<1|1, Mid+1, R); pushup(u); }
Matrix query(int u, int l, int r, int L, int R){ if (l <= L && R <= r) return prod[u]; if (l > Mid) returnquery(u<<1|1, l, r, Mid+1, R); if (Mid+1 > r) returnquery(u<<1, l, r, L, Mid); returnquery(u<<1, l, r, L, Mid) * query(u<<1|1, l, r, Mid+1, R); }
voidmodify(int u, int p, int L, int R){ if (L == R) return prod[u] = { INF, g[pos[L]][0], g[pos[L]][1], g[pos[L]][1], }, void(); if (p <= Mid) modify(u<<1, p, L, Mid); elsemodify(u<<1|1, p, Mid+1, R); pushup(u); }
voiddfs1(int u, int f){ fa[u] = f, sz[u] = 1; for (int i = h[u]; i; i = e[i].nxt) { int to = e[i].to; if (to == f) continue; dfs1(to, u); sz[u] += sz[to]; if (sz[son[u]] < sz[to]) son[u] = to; } }
voiddfs2(int u, int t){ top[u] = t, dfn[u] = ++ts, pos[ts] = u; if (!son[u]) return ed[top[u]] = u, void(); dfs2(son[u], t); for (int i = h[u]; i; i = e[i].nxt) { int to = e[i].to; if (to == fa[u] || to == son[u]) continue; dfs2(to, to); } }
voiddfs3(int u){ g[u][0] = 0, g[u][1] = p[u]; for (int i = h[u]; i; i = e[i].nxt) { int to = e[i].to; if (to == fa[u]) continue; dfs3(to); if (to != son[u]) { g[u][0] += f[to][1]; g[u][1] += min(f[to][0], f[to][1]); } } f[u][0] = g[u][0] + f[son[u]][1]; f[u][1] = g[u][1] + min(f[son[u]][0], f[son[u]][1]); }
voidupdate(int u, int s, int val){ g[u][s] = val;
while (u) { int tp = top[u], nxt = fa[tp]; modify(1, dfn[u], 1, n); Matrix mat = query(1, dfn[tp], dfn[ed[tp]], 1, n); int f0 = min(mat.dat[0][0], mat.dat[0][1]); int f1 = min(mat.dat[1][0], mat.dat[1][1]);