• 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
  • 相关阅读:
    在C#代码中应用Log4Net(二)典型的使用方式
    在C#代码中应用Log4Net(一)简单使用Log4Net
    Windows Azure Active Directory (2) Windows Azure AD基础
    Windows Azure Virtual Network (6) 设置Azure Virtual Machine固定公网IP (Virtual IP Address, VIP) (1)
    Windows Azure Active Directory (1) 前言
    Azure China (6) SAP 应用在华登陆 Windows Azure 公有云
    Microsoft Azure News(3) Azure新的基本实例上线 (Basic Virtual Machine)
    Microsoft Azure News(2) 在Microsoft Azure上运行SAP应用程序
    Microsoft Azure News(1) 新的数据中心Japan East, Japan West and Brazil South
    Windows Azure HandBook (2) Azure China提供的服务
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10731002.html
Copyright © 2020-2023  润新知