• bzoj 4712: 洪水


    [权限题][https://www.lydsy.com/JudgeOnline/status.php?problem_id=4712&jresult=4]

    这道动态(dp)终于不是独立集/覆盖集了

    我们来看看暴力转移

    (dp_x)表示把(x)子树内部全部切断的最小花费

    显然有

    [dp_x=min(a_x,sum_{(x,v)in e}dp_v ) ]

    于是我们可以考虑把所有轻儿子的(dp_v)存下来

    之后就能搞了

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define LL long long
    #define re register
    #define maxn 200005
    #define inf 99999999999999
    inline int read() {
        char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int n,m,num,__;
    struct E{int v,nxt;}e[maxn<<1];
    struct mat{LL a[2][2];}d[maxn<<2];
    int l[maxn<<2],r[maxn<<2];
    int deep[maxn],fa[maxn],pos[maxn],sum[maxn],son[maxn];LL dp[maxn];
    int id[maxn],dfn[maxn],top[maxn],bot[maxn],head[maxn],a[maxn];
    inline void C(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
    void dfs1(int x) {
        sum[x]=1;int maxx=-1;
        for(re int i=head[x];i;i=e[i].nxt) {
            if(deep[e[i].v]) continue;
            deep[e[i].v]=deep[x]+1;fa[e[i].v]=x;
            dfs1(e[i].v);sum[x]+=sum[e[i].v];
            if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
        }
    }
    int dfs2(int x,int topf) {
        top[x]=topf;dfn[x]=++__,id[__]=x;
        if(!son[x]) return bot[x]=x;
        bot[x]=dfs2(son[x],topf);
        for(re int i=head[x];i;i=e[i].nxt) {
            if(top[e[i].v]) continue;
            dfs2(e[i].v,e[i].v);
        }
        return bot[x];
    }
    inline mat operator*(mat a,mat b) {
        mat c;
        c.a[0][0]=min(a.a[0][0]+b.a[0][0],a.a[0][1]+b.a[1][0]);
        c.a[0][1]=min(a.a[0][1]+b.a[1][1],a.a[0][0]+b.a[0][1]);
        c.a[1][0]=min(a.a[1][0]+b.a[0][0],a.a[1][1]+b.a[1][0]);
        c.a[1][1]=min(a.a[1][1]+b.a[1][1],a.a[1][0]+b.a[0][1]);
        return c;
    }
    inline void pushup(int i) {d[i]=d[i<<1]*d[i<<1|1];}
    inline void change(int i,int val) {d[i].a[0][1]=val;while(i) {i>>=1;pushup(i);}}
    inline void push(int i,mat val) {d[i]=val;while(i) {i>>=1;pushup(i);}}
    void build(int x,int y,int i) {
        l[i]=x,r[i]=y;
        if(x==y) {
            int now=id[x];
            for(re int j=head[now];j;j=e[j].nxt) {
                if(deep[e[j].v]<deep[now]||son[now]==e[j].v) continue;
                dp[now]+=dp[e[j].v];
            }
            if(son[now]) d[i].a[0][0]=dp[now];else d[i].a[0][0]=inf;
            d[i].a[0][1]=a[now];
            d[i].a[1][0]=inf,d[i].a[1][1]=0;
            if(son[now]) dp[now]+=dp[son[now]];
            if(!dp[now]||dp[now]>a[now]) dp[now]=a[now];pos[now]=i;
            return;
        }
        int mid=x+y>>1;
        build(mid+1,y,i<<1|1),build(x,mid,i<<1);
        pushup(i);
    }
    mat query(int x,int y,int i) {
        if(x<=l[i]&&y>=r[i]) return d[i];
        int mid=l[i]+r[i]>>1;
        if(y<=mid) return query(x,y,i<<1);
        if(x>mid) return query(x,y,i<<1|1);
        return query(x,y,i<<1)*query(x,y,i<<1|1);
    }
    int main() {
        n=read();
        for(re int i=1;i<=n;i++) a[i]=read();
        for(re int x,y,i=1;i<n;i++) x=read(),y=read(),C(x,y),C(y,x);
        deep[1]=1,dfs1(1),dfs2(1,1),build(1,n,1);
        m=read();int x,y;char opt[2];
        while(m--) {
            scanf("%s",opt);x=read();
            if(opt[0]=='Q') {
                mat now=query(dfn[x],dfn[bot[x]],1);
                printf("%lld
    ",min(now.a[0][0],now.a[0][1]));
            }
            if(opt[0]=='C') {
                y=read();a[x]+=y;
                mat pre=query(dfn[top[x]],dfn[bot[x]],1);
                change(pos[x],a[x]);
                while(1) {
                    if(top[x]==1) break;
                    mat now=query(dfn[top[x]],dfn[bot[x]],1);
                    mat t=d[pos[fa[top[x]]]];
                    t.a[0][0]-=min(pre.a[0][0],pre.a[0][1]);
                    t.a[0][0]+=min(now.a[0][0],now.a[0][1]);
                    x=fa[top[x]];
                    pre=query(dfn[top[x]],dfn[bot[x]],1);push(pos[x],t);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    关于MyEclipse项目的名字的修改对项目导入导出的影响
    关于SQL语句的一些注意事项
    关于Struts2的jsp页面的注释
    关于VS2013常用到的快捷键
    关于Cocos2d-x中定时器的使用总结
    关于Cocos2d-x中打包图集和使用方法
    zend studio 10.6.2 设置默认编码为UTF-8
    zend studio 10.6.2 字体大小 设置
    zend Studio10.6.2汉化
    JQ Ajax 上传文件
  • 原文地址:https://www.cnblogs.com/asuldb/p/10544481.html
Copyright © 2020-2023  润新知