洛谷P4719 【模板】动态 DP 题解 动态DP(DDP)模板题

题目链接:https://www.luogu.com.cn/problem/P4719

解题思路:完全来自 oi.wiki

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5, inf = 1e9;

int f[maxn][2];
int n, m, a[maxn];
int dfn[maxn], id[maxn], ts, fa[maxn], top[maxn], End[maxn], sz[maxn], son[maxn];
vector<int> g[maxn];

struct Matrix {
    int a[2][2];

    Matrix() {
        memset(a, 0, sizeof a);
    }

    Matrix operator * (const Matrix &b) const {
        Matrix c;
        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                c.a[i][j] = max(a[i][0] + b.a[0][j], a[i][1] + b.a[1][j]);
        return c;
    }

} tr[maxn<<2], G[maxn];

#define lson l, mid, u<<1
#define rson mid+1, r, u<<1|1

void push_up(int u) {
    tr[u] = tr[u<<1] * tr[u<<1|1];
}

void build(int l, int r, int u) {
    if (l == r) {
        tr[u] = G[ id[l] ];
        return;
    }
    int mid = l + r >> 1;
    build(lson);
    build(rson);
    push_up(u);
}

Matrix query(int L, int R, int l, int r, int u) {
    if (L <= l && r <= R)
        return tr[u];
    int mid = l + r >> 1;
    if (L <= mid && R > mid)
        return query(L, R, lson) * query(L, R, rson);
    else if (L <= mid)
        return query(L, R, lson);
    else {
        assert(R > mid);
        return query(L, R, rson);
    }
}

void update(int p, int l, int r, int u) {
    if (l == r) {
        tr[u] = G[ id[l] ];
        return;
    }
    int mid = l + r >> 1;
    (p <= mid) ? update(p, lson) : update(p, rson);
    push_up(u);
}

void Update(int x, int val) {
    G[x].a[1][0] += val - a[x];
    a[x] = val;
    while (x) {
        Matrix last = query(dfn[ top[x] ], End[ top[x] ], 1, n, 1);
        update(dfn[x], 1, n, 1);
        Matrix now = query(dfn[ top[x] ], End[ top[x] ], 1, n, 1);

        x = fa[ top[x] ];
        if (!x)
            break;
        G[x].a[0][0] += max(now.a[0][0], now.a[1][0]) - max(last.a[0][0], last.a[1][0]);
        G[x].a[0][1] = G[x].a[0][0];
        G[x].a[1][0] += now.a[0][0] - last.a[0][0];
    }
}

void dfs1(int u, int p) {
    fa[u] = p;
    f[u][1] = a[u];
    f[u][0] = 0;
    sz[u] = 1;
    for (auto v : g[u]) {
        if (v != p) {
            dfs1(v, u);
            f[u][1] += f[v][0];
            f[u][0] += max(f[v][1], f[v][0]);
            sz[u] += sz[v];
            if (sz[v] > sz[ son[u] ])
                son[u] = v;
        }
    }
}

void dfs2(int u, int tp) {
    dfn[u] = ++ts;
    id[ts] = u;
    top[u] = tp;
    End[tp] = ts;
    if (son[u])
        dfs2(son[u], tp);
    G[u].a[1][0] = a[u];
    G[u].a[1][1] = -inf;
    for (auto v : g[u]) {
        if (v != son[u] && v != fa[u]) {
            dfs2(v, v);
            G[u].a[0][0] += max(f[v][1], f[v][0]);
            G[u].a[1][0] += f[v][0];
        }
    }
    G[u].a[0][1] = G[u].a[0][0];
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d", a+i);
    for (int i = 1, u, v; i < n; i++) {
        scanf("%d%d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs1(1, 0);
    dfs2(1, 1);

    build(1, n, 1);

    for (int i = 0, x, y; i < m; i++) {
        scanf("%d%d", &x, &y);
        Update(x, y);
        Matrix res = query(1, End[1], 1, n, 1);
        int ans = max(res.a[0][0], res.a[1][0]);
        printf("%d\n", ans);
    }
    return 0;
}
```
posted @ 2026-03-23 01:06  quanjun  阅读(1)  评论(0)    收藏  举报