luogu P5024 NOIP2018 保卫王国 动态dp

版权声明:_ https://blog.csdn.net/lunch__/article/details/84728971

题意

  • 给你一个树,每次强制选点或者强制不选,询问最小权覆盖

这个东西就是个动态 d p dp 模板题

但是我模板打的不熟练调模板调了好久…

不会的话看这篇博客

强制选点通过把权值改为正无穷负无穷来实现

针对这题转移矩阵是这个样子的 ( i n f S 0 S 1 S 1 ) \left( \begin{matrix} inf & S_0 \\ S_1 & S_1 \end{matrix} \right)

注意实现细节与 i n f inf 的取值

Codes

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;
const ll Inf = 1e17, INF = 1e18;

struct Martix {

    ll a[2][2];

    Martix() {a[0][0] = a[0][1] = a[1][0] = a[1][1] = INF;}
    
    Martix operator * (const Martix &T) const {
        Martix res; 
        for (int i = 0; i < 2; ++ i)
            for (int j = 0; j < 2; ++ j)
                for (int k = 0; k < 2; ++ k)
                    res.a[i][j] = min(res.a[i][j], a[i][k] + T.a[k][j]);
        return res; 
    }

}g[N];

int to[N << 1], nxt[N << 1], head[N], e; 
int st[N], ed[N], rel[N], top[N], cnt;
int size[N], fa[N], heavy[N];
int n, m, a[N];

ll f[N][2];

void P(Martix x) {
    cout << x.a[0][0] << ' ' << x.a[0][1] << endl << x.a[1][0] << ' ' << x.a[1][1] << endl;
}

inline int read() {
    int _ = 0, __ = getchar(), ___ = 1; 
    for (; !isdigit(__); __ = getchar()) if (__ == '-') ___ = -1;
    for (; isdigit(__); __ = getchar()) _ = (_ << 3) + (_ << 1) + (__ ^ 48);
    return _ * ___;
}

void add(int x, int y) {
    to[++ e] = y; nxt[e] = head[x]; head[x] = e;
}

void dfs1(int x) {
    size[x] = 1, f[x][1] = a[x]; 
    for (int i = head[x]; i; i = nxt[i]) if (!size[to[i]]) {
        fa[to[i]] = x, dfs1(to[i]); 
        //注意转移和最大权独立集不一样
        f[x][0] += f[to[i]][1];
        f[x][1] += min(f[to[i]][0], f[to[i]][1]);
        size[x] += size[to[i]];
        if (size[to[i]] > size[heavy[x]])
            heavy[x] = to[i];
    }
    ll s0 = f[x][0] - f[heavy[x]][1], s1 = f[x][1] - min(f[heavy[x]][1], f[heavy[x]][0]);
    g[x].a[1][0] = s0, g[x].a[0][1] = g[x].a[1][1] = s1; 
    //转移不一样构造的转移矩阵也不一样
}

void dfs2(int x, int ancestor) {
    rel[ed[top[x] = ancestor] = st[x] = ++ cnt] = x; 
    if (heavy[x]) dfs2(heavy[x], ancestor);
    for (int i = head[x]; i; i = nxt[i]) 
        if (!top[to[i]]) dfs2(to[i], to[i]);
}

struct Segment_Tree {
#define mid ((l + r) >> 1)
#define ls (bh << 1)
#define rs (ls | 1)
#define lson ls, l, mid
#define rson rs, mid + 1, r

    Martix S[N << 2]; 

    void pushup(int bh) {
        S[bh] = S[rs] * S[ls];
    }

    void build(int bh, int l, int r) {
        if (l == r) S[bh] = g[rel[l]];
        else build(lson), build(rson), pushup(bh);
    }

    void update(int bh, int l, int r, int x) {
        if (l == r) S[bh] = g[rel[l]];
        else {
            if (x <= mid) update(lson, x);
            else update(rson, x);
            pushup(bh);
        }在这里插入代码片
    }

    Martix query(int bh, int l, int r, int x, int y) {
        if (x <= l && r <= y) return S[bh];
        if (y <= mid) return query(lson, x, y);
        if (x > mid) return query(rson, x, y);
        return query(rson, x, y) * query(lson, x, y);
    }

}T;

void modify(int x, ll y) {
    Martix now, lst;
    for(; x; x = fa[top[x]]) {
        ll del0, del1; 
        if (y) del1 = y, del0 = y = 0; 
        else {
            del0 = now.a[1][1] - lst.a[1][1];
            del1 = min(now.a[1][0], now.a[1][1]) - min(lst.a[1][0], lst.a[1][1]);
        }
        lst = T.query(1, 1, n, st[top[x]], ed[top[x]]);
        g[x].a[1][0] += del0, g[x].a[0][1] += del1, g[x].a[1][1] += del1;
        T.update(1, 1, n, st[x]);
        //一定注意先更新再查= =我卡在这卡了好久
        now = T.query(1, 1, n, st[top[x]], ed[top[x]]);
    }
}

int main() {
#ifdef ylsakioi
    freopen("5024.in", "r", stdin);
    freopen("5024.out", "w", stdout);
#endif

    ll A, B, X, Y, ans = 0; char S[N];

    n = read(), m = read(), scanf("%s", S);
    for (int i = 1; i <= n; ++ i)
        a[i] = read();
    for (int i = 1; i < n; ++ i) {
        X = read(), Y = read();
        add(X, Y), add(Y, X);
    }

    dfs1(1), dfs2(1, 1), T.build(1, 1, n);


//这里一般不会出问题,要挂了肯定上面写错了
    for (int i = 1; i <= m; ans = 0, ++ i) {
        A = read(), X = read(), B = read(), Y = read();
        if (X) X = -Inf, ans -= X; else X = Inf;
        if (Y) Y = -Inf, ans -= Y; else Y = Inf;
        modify(A, X), modify(B, Y);
        Martix res = T.query(1, 1, n, st[1], ed[1]);
        modify(A, -X), modify(B, -Y);
        ans += min(res.a[1][0], res.a[1][1]);
        printf("%lld\n", ans > Inf ? -1 : ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/84728971