zoukankan      html  css  js  c++  java
  • noip2018 保卫王国

    动态维护树上最小点覆盖

    $n leq 100000$

    sol:动态 dp,请

    先写一个树上的 dp

    $f_{(x,0)} = sum f_{(to,1)}$

    $f_{(x,1)} = v_x + sum f_{(to,0)}$

    首先考虑链上的情形

    链上的转移方程非常的清真,它是

    $f_{(x,0)} = f_{(to,1)}$

    $f_{(x,1)} = v_x + f_{(to,0)}$

    $to$ 就是 $x$ 左边的点

    这个方程是一个广义的常系数线性递推(把 min 看成线性),可以用一个广义的矩阵来维护

    维护一个矩阵 $ left[ egin{matrix} 0 & infty \ v_x & v_x end{matrix} ight]$

    则 $ left[ egin{matrix} 0 & infty \ v_x & v_x end{matrix} ight] imes left[ egin{matrix} f_{(x-1,0)} \ f_{(x-1,1)} end{matrix} ight] = left[ egin{matrix} f_{(x,0)} \ f_{(x,1)} end{matrix} ight]$

    于是上树的情况就是:在重链上维护这个转移式,因为一个点到根最多经过 logn 条重链,所以复杂度是 $O(nlog^2n)$

    上树的时候会发现矩阵有一些变化,因为还要维护轻链上的转移,我们可以设 $A = sumlimits_{v in light_x} f_{(v,1)},B = v_x + sumlimits_{v in light_x} min(f_{(v,1)},f_{(v,0)})$

    则每个点的矩阵是

    $ left[ egin{matrix} A & infty \ B & B end{matrix} ight]$

    维护这个的同时维护一下 $g$ 数组表示这个点所有轻儿子的信息即可

    写了好几次动态 dp 了,每次都重学

    这是最后一次(flag

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read() {
        int x = 0,f = 1; char ch = getchar();
        for(; !isdigit(ch); ch = getchar())if(ch == '-') f = -f;
        for(; isdigit(ch); ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const LL oo = 1e10, maxn = 5e5 + 10;
    /*
    A inf
    B B
    
    A = sigma (light, 1)
    B = val + sigma(light, min(0, 1))
    
    A inf   hv     (0)
    B B     hv     (1)
    */
    struct Matrix {
        LL a[2][2];
        Matrix(){ rep(i, 0, 1) rep(j, 0, 1) a[i][j] = oo; }
        Matrix(LL x, LL y){ a[0][1] = x, a[1][0] = a[1][1] = y, a[0][0] = oo; }
        Matrix operator * (const Matrix &b) const {
            Matrix c;
            rep(i, 0, 1) rep(j, 0, 1) rep(k, 0, 1) c.a[i][j] = min(c.a[i][j], a[i][k] + b.a[k][j]);
            return c;
        }
    };
    
    Matrix seg[maxn << 2], Mod;
    #define ls (x << 1)
    #define rs ((x << 1) | 1)
    inline void update(int x, int l, int r, int pos, Matrix Mod) {
        //cout << x << endl;
        if(l == r) { seg[x] = Mod; return; }
        int mid = (l + r) >> 1;
        if(pos <= mid) update(ls, l, mid, pos, Mod);
        else update(rs, mid+1, r, pos, Mod);
        seg[x] = seg[ls] * seg[rs];
    }
    inline Matrix query(int x, int l, int r, int L, int R) {
        if(L <= l && r <= R) return seg[x];
        int mid = (l + r) >> 1; Matrix ret;
        ret.a[0][1] = ret.a[1][0] = oo; ret.a[0][0] = ret.a[1][1] = 0;
        if(L <= mid) ret = ret * query(ls, l, mid, L, R);
        if(R > mid) ret = ret * query(rs, mid+1, r, L, R);
        return ret;
    }
    
    int n, m, a[maxn]; LL f[maxn][2], g[maxn][2];
    vector<int> G[maxn];
    int fa[maxn], mxs[maxn], bl[maxn], pos[maxn], size[maxn], bot[maxn], dfn;
    inline void dfs1(int x) {
        size[x] = 1; f[x][1] = a[x];
        for(auto to : G[x]) {
            if(to == fa[x]) continue;
            fa[to] = x;
            dfs1(to); size[x] += size[to];
            if(!mxs[x] || size[to] > size[mxs[x]]) mxs[x] = to;
            f[x][0] += f[to][1]; f[x][1] += min(f[to][0], f[to][1]);
        } //cout << x << " : " << mxs[x] << endl;
    }
    inline void dfs2(int x, int col) {
        bl[x] = col; pos[x] = ++dfn; g[x][1] = a[x];
        //cout << pos[x] << " " << bl[x] << endl;
        if(!mxs[x]) {
            update(1, 1, n, pos[x], Matrix(g[x][0], g[x][1]));
            bot[col] = dfn;
            return;
        } dfs2(mxs[x], col);
        for(auto to : G[x]) if(to != mxs[x] && to != fa[x]) {
            g[x][0] += f[to][1];
            g[x][1] += min(f[to][1], f[to][0]);
            dfs2(to, to);
        }
        update(1, 1, n, pos[x], Matrix(g[x][0], g[x][1]));
    }
    inline LL Modify(int x) {
        update(1, 1, n, pos[x], Matrix(g[x][0], g[x][1])); x = bl[x];
        while(x > 1) {
            Matrix cur = query(1, 1, n, pos[x], bot[x]);
            g[fa[x]][0] -= f[x][1];
            g[fa[x]][1] -= min(f[x][0], f[x][1]);
            f[x][0] = cur.a[0][1], f[x][1] = cur.a[1][1];
            g[fa[x]][0] += f[x][1];
            g[fa[x]][1] += min(f[x][0], f[x][1]);
            int cp = fa[x];
            update(1, 1, n, pos[cp], Matrix(g[cp][0], g[cp][1]));
            x = bl[fa[x]];
        }
    //    cout << bot[1] << endl;
        Matrix ans = query(1, 1, n, 1, bot[1]);
    //    cout << "COMP" << endl;
        return min(ans.a[0][1], ans.a[1][1]);
    }
    int main() {
        //freopen("defense.in","r",stdin);
        //freopen("defense.out","w",stdout);
        n = read(), m = read(); scanf("%*s");
        rep(i, 1, n) a[i] = read();
        rep(i, 2, n) {
            int u = read(), v = read();
            G[u].push_back(v); G[v].push_back(u);
        } dfs1(1); dfs2(1, 1);
        while(m--) {
            int a = read(), x = 1 ^ read(), b = read(), y = 1 ^ read();
            LL tmp1 = g[a][x], tmp2 = g[b][y];
            g[a][x] = oo, Modify(a);
            g[b][y] = oo; LL ans = Modify(b);
            if(ans >= oo) cout << -1 << '
    ';
            else cout << ans << '
    ';
            g[a][x] = tmp1, Modify(a);
            g[b][y] = tmp2, Modify(b);
        }
    }
    View Code
  • 相关阅读:
    css3文字单位rem 设置文字大小
    JS实现多物体width缓冲运动实例
    vs 你不得不会的调试方式
    C# 常用修饰符
    富文本编辑器tinymce
    Swagger简单实例
    marquee标签详解
    table数据跑马灯效果
    SqlServer发布订阅
    ORM概述及常用ORM框架
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10731002.html
Copyright © 2011-2022 走看看