本题博主用的是ddp写法,如果想学倍增的话请退回去。
Solution
这道题如果用ddp的话就是道模板题了吧。
必须选看成把权值赋为负无穷,不选看成把权值赋为无穷,如果最后答案大于无穷或小于负无穷即无解。
最后要复原。
Code(重链剖分+线段树)
#include <iostream> #include <cstdio> #include <cstring> #include <map> using namespace std; typedef long long ll; const int N = 100010; const ll inf = 0x3f3f3f3f3f3f3f3f; namespace IO{ template <typename T> void read(T &x) { T f = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1; for (x = 0; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; x *= f; } template <typename T> void write(T x) { if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void print(T x) { if (x < 0) putchar('-'), x = -x; write(x); putchar(' '); } }using namespace IO; int n, m; ll p[N]; char s[10]; namespace QXX{ struct node{ int pre, to; }edge[N << 1]; int head[N], tot; inline void add(int u, int v) { edge[++tot] = node{head[u], v}; head[u] = tot; } }using namespace QXX; namespace MATRIX{ template <typename T> void cmin(T &x, T y) {if (y < x) x = y;} template <typename T> void cmax(T &x, T y) {if (y > x) x = y;} struct Matrix{ ll arr[3][3]; }; inline void init(Matrix &X) { memset(X.arr, 0x3f, sizeof(X.arr)); } inline Matrix Mul(Matrix X, Matrix Y) { Matrix Z; init(Z); for (int i = 1; i <= 2; i++) for (int j = 1; j <= 2; j++) for (int k = 1; k <= 2; k++) cmin(Z.arr[i][j], X.arr[i][k] + Y.arr[k][j]); return Z; } }using namespace MATRIX; namespace TCP{ Matrix A[N]; ll dp[N][2]; int dfn[N], pos[N], top[N], End[N], num; int sz[N], fa[N], son[N]; void dfs1(int x) { sz[x] = 1; for (int i = head[x]; i; i = edge[i].pre) { if (edge[i].to == fa[x]) continue; fa[edge[i].to] = x; dfs1(edge[i].to); sz[x] += sz[edge[i].to]; if (sz[edge[i].to] > sz[son[x]]) son[x] = edge[i].to; } } void dfs2(int x, int chain) { dfn[x] = ++num, top[x] = chain, pos[dfn[x]] = x; init(A[x]); A[x].arr[1][1] = A[x].arr[1][2] = p[x]; A[x].arr[2][1] = 0; if (son[x]) dfs2(son[x], chain), dp[x][0] = dp[son[x]][1], dp[x][1] = min(dp[son[x]][0], dp[son[x]][1]); else End[chain] = dfn[x]; for (int i = head[x]; i; i = edge[i].pre) { if (edge[i].to == fa[x] || edge[i].to == son[x]) continue; dfs2(edge[i].to, edge[i].to); A[x].arr[2][1] += dp[edge[i].to][1]; A[x].arr[1][1] += min(dp[edge[i].to][1], dp[edge[i].to][0]); A[x].arr[1][2] = A[x].arr[1][1]; } dp[x][0] += A[x].arr[2][1]; dp[x][1] += A[x].arr[1][1]; } }using namespace TCP; namespace Segment_Tree{ struct Segment{ Matrix val; }tr[N << 2]; inline void push_up(int p) {tr[p].val = Mul(tr[p << 1].val, tr[p << 1 | 1].val);} void build(int p, int l, int r) { if (l == r) { tr[p].val = A[pos[l]]; return; } int mid = (l + r) >> 1; build(p << 1, l, mid); build(p << 1 | 1, mid + 1, r); push_up(p); } void change(int p, int l, int r, int Pos) { if (l == r) { tr[p].val = A[pos[l]]; return; } int mid = (l + r) >> 1; if (Pos <= mid) change(p << 1, l, mid, Pos); else change(p << 1 | 1, mid + 1, r, Pos); push_up(p); } Matrix query(int p, int l, int r, int x, int y) { if (x <= l && r <= y) return tr[p].val; int mid = (l + r) >> 1; if (y <= mid) return query(p << 1, l, mid, x, y); else if (x > mid) return query(p << 1 | 1, mid + 1, r, x, y); else return Mul(query(p << 1, l, mid, x, mid), query(p << 1 | 1, mid + 1, r, mid + 1, y)); } }using namespace Segment_Tree; inline void update(int a, ll b) {//将节点 a 的权值改为 b A[a].arr[1][1] += b - p[a]; A[a].arr[1][2] = A[a].arr[1][1]; p[a] = b; while (a) { Matrix bef = query(1, 1, n, dfn[top[a]], End[top[a]]); change(1, 1, n, dfn[a]); Matrix aft = query(1, 1, n, dfn[top[a]], End[top[a]]); a = fa[top[a]]; A[a].arr[1][1] += min(aft.arr[1][1], aft.arr[2][1]) - min(bef.arr[1][1], bef.arr[2][1]); A[a].arr[1][2] = A[a].arr[1][1]; A[a].arr[2][1] += aft.arr[1][1] - bef.arr[1][1]; } } int main() { read(n); read(m); scanf("%s", s + 1); for (int i = 1; i <= n; i++) read(p[i]); for (int i = 1, u, v; i < n; i++) read(u), read(v), add(u, v), add(v, u); dfs1(1); dfs2(1, 1); build(1, 1, n); while (m--) { int a, x, b, y; read(a); read(x); read(b); read(y); ll out = 0, tmpa = p[a], tmpb = p[b]; if (x == 0) update(a, inf); else update(a, -inf), out += inf + tmpa; if (y == 0) update(b, inf); else update(b, -inf), out += inf + tmpb; Matrix ans = query(1, 1, n, dfn[top[1]], End[top[1]]); out += min(ans.arr[1][1], ans.arr[2][1]); if (-inf < out && out < inf) print(out); else print(-1); update(a, tmpa); update(b, tmpb); } return 0; }