luoguP5024 保衛王國 動態dp
阿新 • • 發佈:2018-12-23
題目大意:
emmmmm
題解:
QAQ
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define ll long long #define ri register int #define rep(io, st, ed) for(ri io = st; io <= ed; io ++) #define drep(io, ed, st) for(ri io = ed; io >= st; io --) #define gc getchar inline int read() { int p = 0, w = 1; char c = gc(); while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); } while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc(); return p * w; } const int sid = 5e5 + 5; const ll inf = 1e17; char mm[50]; int n, m, id, cnp, tim; int ls[sid], rs[sid], rt[sid]; int cap[sid], nxt[sid], node[sid]; int sz[sid], son[sid], fa[sid], anc[sid]; int dfn[sid], ind[sid], L[sid], V[sid]; ll g[sid][2]; struct Mar { ll dp[2][2]; inline ll* operator [] (const int x) { return dp[x]; } } F[sid]; inline void addedge(int u, int v) { nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v; } #define cur node[i] inline void dfs(int o) { sz[o] = 1; for(int i = cap[o]; i; i = nxt[i]) if(cur != fa[o]) { fa[cur] = o; dfs(cur); sz[o] += sz[cur]; if(sz[cur] > sz[son[o]]) son[o] = cur; } } inline void dfs(int o, int ac) { anc[o] = ac; L[ac] ++; dfn[o] = ++ tim; ind[tim] = o; if(!son[o]) return; dfs(son[o], ac); for(int i = cap[o]; i; i = nxt[i]) if(cur != fa[o] && cur != son[o]) dfs(cur, cur); } inline void upd(int o) { int lc = ls[o], rc = rs[o]; F[o][0][0] = min(F[rc][0][0] + F[lc][0][0], F[rc][0][1] + F[lc][1][0]); F[o][0][1] = min(F[rc][0][0] + F[lc][0][1], F[rc][0][1] + F[lc][1][1]); F[o][1][0] = min(F[rc][1][0] + F[lc][0][0], F[rc][1][1] + F[lc][1][0]); F[o][1][1] = min(F[rc][1][0] + F[lc][0][1], F[rc][1][1] + F[lc][1][1]); } inline void build(int &o, int l, int r) { o = ++ id; if(l == r) { int u = ind[l]; F[o][0][0] = F[o][1][0] = g[u][1]; F[o][0][1] = g[u][0]; F[o][1][1] = inf; return; } int mid = (l + r) >> 1; build(ls[o], l, mid); build(rs[o], mid + 1, r); upd(o); } inline void mdf(int o, int l, int r, int p) { if(l == r) { int u = ind[l]; F[o][0][0] = F[o][1][0] = g[u][1]; F[o][0][1] = g[u][0]; F[o][1][1] = inf; return; } int mid = (l + r) >> 1; if(p <= mid) mdf(ls[o], l, mid, p); else mdf(rs[o], mid + 1, r, p); upd(o); } inline void build(int o) { int leaf = 0; g[o][0] = 0; g[o][1] = V[o]; for(int i = cap[o]; i; i = nxt[i]) if(cur != fa[o]) { leaf = 1; build(cur); if(cur == son[o]) continue; g[o][0] += F[rt[cur]][0][0]; g[o][1] += min(F[rt[cur]][0][0], F[rt[cur]][0][1]); } if(anc[o] == o) build(rt[o], dfn[o], dfn[o] + L[o] - 1); } inline void mdf(int o, int opt, int nx) { int now = anc[o], up = fa[now], lst = o; if(opt == 1) g[o][0] += inf * nx; else g[o][1] += inf * nx; while(lst) { g[up][0] -= F[rt[now]][0][0]; g[up][1] -= min(F[rt[now]][0][0], F[rt[now]][0][1]); mdf(rt[now], dfn[now], dfn[now] + L[now] - 1, dfn[lst]); g[up][0] += F[rt[now]][0][0]; g[up][1] += min(F[rt[now]][0][0], F[rt[now]][0][1]); lst = up; now = anc[up]; up = fa[now]; } } inline void solve() { int a = read(), x = read(), b = read(), y = read(); mdf(a, x, 1); mdf(b, y, 1); ll ans = min(F[rt[1]][0][0], F[rt[1]][0][1]); ans = min(F[rt[1]][0][0], F[rt[1]][0][1]); if(ans >= 1e15) printf("-1\n"); else printf("%lld\n", ans); mdf(a, x, -1); mdf(b, y, -1); } int main() { n = read(); m = read(); scanf("%s", mm + 1); rep(i, 1, n) V[i] = read(); rep(i, 2, n) { int u = read(), v = read(); addedge(u, v); addedge(v, u); } dfs(1); dfs(1, 1); build(1); rep(i, 1, m) solve(); return 0; }
大家都會寫的題,不是嗎?