• 【题解】【BZOJ】BZOJ4712 洪水


    BZOJ4712 洪水

    BZOJ4712 洪水

    1 题外话

    鸽了好久

    2 sol

    首先考虑没有修改的情况,题目变成一个简单的dp

    设(f_i) 表示从(i) 出发走不到所有其叶子节点的最小代价

    则(f_i=min(V_i,sum_{t}f_t)) 其中(V_i) 为删去(i) 点的权值,(t) 是(i) 的儿子

    对树进行重链剖分,设(g_i) 表示(i) 的所有轻儿子的(f) 的和

    则有(f_i=min(V_i,g_i+f_son)) ,其中(son) 表示(i) 的重儿子

    将矩阵乘法写成min和+的形式

    就有(egin{bmatrix}0&f_hend{bmatrix} imesegin{bmatrix}0&V_i\infty&g[i]end{bmatrix}=egin{bmatrix}0&f_iend{bmatrix})

    直接用树剖ddp即可

    3 code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define int long long
    
    const int N=200010;
    const int inf=2e9;
    
    inline void read(int &x) {
        x=0;
        int f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9') {
            if (ch=='-') {
                f=-1;
            }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9') {
            x=x*10+ch-'0';
            ch=getchar();
        }
        x*=f;
    }
    
    struct note {
        int t;
        int next;
    };
    
    int n,m;
    int cnt;
    int head[N];
    note e[N<<1];
    
    inline void add(int x,int y) {
        e[++cnt].t=y;
        e[cnt].next=head[x];
        head[x]=cnt;
    }
    
    struct mat {
        int a[2][2];
        mat(int ax=inf,int b=inf,int c=inf,int d=inf) {
            a[0][0]=ax;
            a[0][1]=b;
            a[1][0]=c;
            a[1][1]=d;
        }
        inline void init_min() {
            for(int i=0;i<2;i++) {
                a[i][i]=0;
            }
        }
    };
    
    inline mat operator * (const mat &x,const mat &y) {
        mat res;
        for(int i=0;i<2;i++) {
            for(int k=0;k<2;k++) {
                for(int j=0;j<2;j++) {
                    res.a[i][j]=min(res.a[i][j],x.a[i][k]+y.a[k][j]);
                }
            }
        }
        return res;
    }
    
    int val[N];
    
    namespace HLD {
    
    int tot;
    int dep[N],fa[N],siz[N],son[N];
    int dfn[N],idfn[N],top[N],bot[N];
    
    void dfs1(int p,int fat) {
        dep[p]=dep[fat]+1;
        fa[p]=fat;
        siz[p]=1;
        int max_siz=-1;
        for(int i=head[p];i+1;i=e[i].next) {
            int t=e[i].t;
            if (t==fat) {
                continue;
            }
            dfs1(t,p);
            siz[p]+=siz[t];
            if (siz[t]>max_siz) {
                max_siz=siz[t];
                son[p]=t;
            }
        }
    }
    
    void dfs2(int p,int top_p) {
        top[p]=top_p;
        dfn[p]=++tot;
        idfn[tot]=p;
        bot[p]=p;
        if (son[p]) {
            dfs2(son[p],top_p);
            bot[p]=bot[son[p]];
        }
        for(int i=head[p];i+1;i=e[i].next) {
            int t=e[i].t;
            if (t==son[p]||t==fa[p]) {
                continue;
            }
            dfs2(t,t);
        }
    }
    
    mat t[N<<2],tmp[N];
    
    void build(int p,int l,int r) {
        if (l==r) {
            t[p]=tmp[idfn[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
        t[p]=t[p<<1|1]*t[p<<1];
    }
    
    void modify(int p,int l,int r,int x) {
        if (l==r) {
            t[p]=tmp[idfn[l]];
            return;
        }
        int mid=(l+r)>>1;
        if (x<=mid) {
            modify(p<<1,l,mid,x);
        } else {
            modify(p<<1|1, mid+1, r, x);
        }
        t[p]=t[p<<1|1]*t[p<<1];
    }
    
    mat query(int p,int l,int r,int L,int R) {
        if (l==L&&r==R) {
            return t[p];
        }
        int mid=(l+r)>>1;
        if (R<=mid) {
            return query(p<<1,l,mid,L,R);
        }
        if (L>mid) {
            return query(p<<1|1,mid+1,r,L,R);
        }
        return query(p<<1|1,mid+1,r,mid+1,R)*query(p<<1,l,mid,L,mid);
    }
    
    int f[N],g[N];
    
    void pre_dp(int p) {
        f[p]=val[p];
        if (son[p]) {
            pre_dp(son[p]);
            f[p]=min(f[p],f[son[p]]);
        } else {
            g[p]=inf;
        }
        for(int i=head[p];i+1;i=e[i].next) {
            int t=e[i].t;
            if (t==fa[p]||t==son[p]) {
                continue;
            }
            pre_dp(t);
            g[p]+=f[t];
        }
        f[p]=min(f[p]+g[p],val[p]);
        tmp[p]=mat(0,val[p],inf,g[p]);
    }
    
    inline int get(int p) {
        return query(1, 1, n, dfn[p], dfn[bot[p]]).a[0][1];
    }
    
    inline void mdf(int p) {
        while(p) {
            tmp[p]=mat(0,val[p],inf,g[p]);
            modify(1,1,n,dfn[p]);
            p=top[p];
            if (p==1) {
                break;
            }
            g[fa[p]]-=f[p];
            f[p]=get(p);
            g[fa[p]]+=f[p];
            p=fa[p];
        }
    }
    
    }
    
    signed main() {
        memset(head,-1,sizeof(head));
        read(n);
        for(int i=1;i<=n;i++) {
            read(val[i]);
        }
        for(int i=1;i<n;i++) {
            int x,y;
            read(x),read(y);
            add(x,y);
            add(y,x);
        }
        HLD::dfs1(1,0);
        HLD::dfs2(1,1);
        HLD::pre_dp(1);
        HLD::build(1,1,n);
        read(m);
        for(int i=1;i<=m;i++) {
            char ch=getchar();
            while(ch!='Q'&&ch!='C') {
                ch=getchar();
            }
            int x;
            read(x);
            if (ch=='Q') {
                printf("%lld
    ",HLD::get(x));
            } else {
                int v;
                read(v);
                val[x]+=v;
                HLD::mdf(x);
            }
        }
        return 0;
    }
    

    4 注意

    矩阵乘法没有交换律(调了半个小时的罪魁祸首)

    代码中线段树的询问写法和平常写的效果相同但不用多写一个单位矩阵(我不会找这种乘法定义下的单位矩阵)

    记得开long long

    Author: tt66ea

    Created: 2021-07-15 周四 15:23

    Validate

  • 相关阅读:
    《飞得更高孙正义传》成为亚洲首富肯定有原因
    AutoController通用自动增删查改
    Silverlight学习笔记第一季(3)扯扯ComboBox
    Silverlight学习笔记第一季(1)DataGrid
    菜鸟混社区之如何看待社区的口水战?
    局部化页面和效率CMS实践系列总结
    图片猜成语(思维@娱乐)
    接口+泛型强大的Repository
    Silverlight学习笔记第一季(2)Listbox横向绑定数据
    poj 2954 Triangle (pick 定理 的应用 )
  • 原文地址:https://www.cnblogs.com/tt66ea-blog/p/15015788.html
Copyright © 2020-2023  润新知