• bzoj4712 洪水


    题目描述:

    给出一棵$n(n<=200000)$的树。每个点有一个权值$w$,表示堵上这个点的花费。

    $m$组操作,操作一为将点$x$的权值加上一个非负整数$d$,操作二为询问以点$x$为根的子树内堵上所有根到叶节点路径的最小花费。

    题解:

    设$h[x]$为$x$的所有子节点的最小花费之和。

    一眼看出$dp[i]=min(w[i],h[i])$

    由于每次$d$非负,我们可以发现每次只会更新$x$的$w$值,

    可能更新一条链上$h$值。

    于是树剖维护$dp$。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 200050
    #define ll long long
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,hed[N],cnt,m;
    char ch[2];
    struct EG
    {
        int to,nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int fa[N],son[N],dep[N],siz[N],top[N];
    ll h[N],w[N],ff[N];
    void dfs1(int u,int f)
    {
        fa[u]=f;
        siz[u]=1;
        dep[u]=dep[f]+1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==f)continue;
            dfs1(to,u);
            siz[u]+=siz[to];
            h[u]+=ff[to];
            if(siz[to]>siz[son[u]])son[u]=to;
        }
        if(siz[u]==1)h[u]=0x3f3f3f3f;
        ff[u] = min(w[u],h[u]);
    }
    int tin[N],tim,pla[N];
    void dfs2(int u,int tp)
    {
        tin[u]=++tim,pla[tim]=u;
        top[u] = tp;
        if(son[u])
        {
            dfs2(son[u],tp);
            for(int j=hed[u];j;j=e[j].nxt)
            {
                int to = e[j].to;
                if(to==fa[u]||to==son[u])continue;
                dfs2(to,to);
            }
        }
    }
    struct segtree
    {
        ll v1[N<<2],tag[N<<2];//min(w-h) h
        void add(int u,ll d)
        {
            v1[u]-=d;
            tag[u]+=d;
        }
        void pushdown(int u)
        {
            if(tag[u])
            {
                add(u<<1,tag[u]);
                add(u<<1|1,tag[u]);
                tag[u]=0;
            }
        }
        void update(int u)
        {
            v1[u] = min(v1[u<<1],v1[u<<1|1]);
        }
        void build(int l,int r,int u)
        {
            if(l==r)
            {
                v1[u] = w[pla[l]]-h[pla[l]];
                tag[u] = h[pla[l]];
                return ;
            }
            int mid = (l+r)>>1;
            build(l,mid,u<<1);
            build(mid+1,r,u<<1|1);
            update(u);
        }
        void insert(int l,int r,int u,int ql,int qr,ll d)//h+=d
        {
            if(l==ql&&r==qr)
            {
                add(u,d);
                return ;
            }
            pushdown(u);
            int mid = (l+r)>>1;
            if(qr<=mid)insert(l,mid,u<<1,ql,qr,d);
            else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,d);
            else insert(l,mid,u<<1,ql,mid,d),insert(mid+1,r,u<<1|1,mid+1,qr,d);
            update(u);
        }
        void ins(int l,int r,int u,int qx,ll d)//w+=d
        {
            if(l==r)
            {
                v1[u]+=d;
                return ;
            }
            pushdown(u);
            int mid = (l+r)>>1;
            if(qx<=mid)ins(l,mid,u<<1,qx,d);
            else ins(mid+1,r,u<<1|1,qx,d);
            update(u);
        }
        ll query1(int l,int r,int u,int ql,int qr)//min(w-h)
        {
            if(l==ql&&r==qr)return v1[u];
            pushdown(u);
            int mid = (l+r)>>1;
            if(qr<=mid)return query1(l,mid,u<<1,ql,qr);
            else if(ql>mid)return query1(mid+1,r,u<<1|1,ql,qr);
            else return min(query1(l,mid,u<<1,ql,mid),query1(mid+1,r,u<<1|1,mid+1,qr));
        }
        ll query2(int l,int r,int u,int qx)//h
        {
            if(l==r)return tag[u];
            pushdown(u);
            int mid = (l+r)>>1;
            if(qx<=mid)return query2(l,mid,u<<1,qx);
            else return query2(mid+1,r,u<<1|1,qx);
        }
    }tr;
    int get_lim(int x,ll d)
    {
        int l = tin[top[x]],r = tin[x],ans = l-1;
        while(l<=r)
        {
            int mid = (l+r)>>1;
            if(tr.query1(1,n,1,mid,tin[x])>=d)
            {
                r = mid-1;
            }else
            {
                ans = mid;
                l = mid+1;
            }
        }
        return pla[ans];
    }
    ll F(int x)
    {
        return min(w[x],tr.query2(1,n,1,tin[x]));
    //    return min(w[x],h[x]);
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
        n=rd();
        for(int i=1;i<=n;i++)w[i] = rd();
        for(int f,t,i=1;i<n;i++)
        {
            f = rd(),t = rd();
            ae(f,t),ae(t,f);
        }
        dfs1(1,0),dfs2(1,1);
        tr.build(1,n,1);
        m = rd();
        int x,y;ll d,f0,f1;
        for(int i=1;i<=m;i++)
        {
            scanf("%s",ch);
            if(ch[0]=='Q')
            {
                x = rd();
                printf("%lld
    ",F(x));
            }else
            {
                x = rd(),d = rd();
    /*            f0 = F(x);
                w[x]+=d;
                f1 = F(x);
                d = f1-f0;
                x = fa[x];
                while(x&&d)
                {
                    f0 = F(x);
                    h[x]+=d;
                    f1 = F(x);
                    x = fa[x];
                    d = f1-f0;
                }*/
                f0 = F(x);
                w[x]+=d;
                tr.ins(1,n,1,tin[x],d);//w+=d
                f1 = F(x);
                d = f1-f0;
                x = fa[x];
                while(x&&d)
                {
                    if(tr.query1(1,n,1,tin[top[x]],tin[x])>=d)
                    {
                        tr.insert(1,n,1,tin[top[x]],tin[x],d);
                        x = fa[top[x]];
                        continue;
                    }
                    y = get_lim(x,d);
                    f0 = F(y);
                    tr.insert(1,n,1,tin[y],tin[x],d);
                    f1 = F(y);
                    x = fa[y],d = f1-f0;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    selenium批量执行脚本操作
    Monkey压力测试操作步骤说明
    loadrunner整体压测执行操作步骤
    selenium3+python3.6爬页面源码的代码
    unittest_API自动化脚本应用
    Python3.7版本unittest框架添加用例的方法
    python3中报错:TypeError: 'range' object doesn't support item deletion
    构建Hadoop集群在线datanode不在线
    Nomodulenamed pip._internal怎么解决
    模拟登陆京东并访问我的订单
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10218350.html
Copyright © 2020-2023  润新知