• bzoj5210最大连通子块和


    • 题解:

      • 考虑朴素的dp:$$f_{u} = max(sum_{v} f_{v} + w_{u} , 0)  h_{u} = max( max_{v} { h_{v} }  , h_{u} )$$
      • 考虑利用树剖修改:记$son_{u}$为$u$的重儿子,$g_{u}$为$u$所有轻儿子之和加$w_{u}$;
      • 方程变成:
      • $g_{u} = w_{u} +  sum_{v!=son_{u}} f_{v}  $
      • $f_{u}  = max(f_{son_{u}}+ g_{u} , 0) $
      • $h_{u} = max( max_{v} {h_{v} }  , h_{u} )$
      • 一个一个讨论:
      • 首先$g$直接修改:当修改一个点时,$w_{u}$改变$g_{u}$改变,向上跳到轻链继续修改,这只有$log$次;
      • 注意到$h$在一条重链上被写成了$g$的最大子段和,同时一个点的$f$就是$g$的最大左段和,这可以用线段树维护;
      • 还需要维护用来统计答案的$h$,对每个点用一个堆记录轻儿子的$h$值,再把堆顶元素一起存到线段树里即可;
      • 查询只需要查询一个点到链底的区间;
    #include<bits/stdc++.h>
    #define ll long long 
    #define ls (k<<1)
    #define rs (k<<1|1)
    using namespace std;
    const int N=200010;
    int n,m,w[N],sz[N],st[N],ed[N],fa[N],tp[N],sn[N],hd[N],o,idx,id[N];
    ll f[N],g[N],h[N],s[N<<2],sl[N<<2],sr[N<<2],ss[N<<2],mx[N<<2];
    struct Edge{int v,nt;}E[N<<1];
    struct data{
        priority_queue<ll>A,B;
        void push(ll x){A.push(x);}
        void pop(ll x){B.push(x);}
        ll top(){
            while(!B.empty()&&A.top()==B.top())A.pop(),B.pop();
            return A.empty()?0:A.top();
        }
    }q[N];
    char gc(){
        static char*p1,*p2,s[1000000];
        if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
        return(p1==p2)?EOF:*p1++;
    }
    int rd(){
        int x=0,f=1;char c=gc();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=gc();}
        return x*f;
    }
    int gt(){
        char c=gc();while(!isalpha(c))c=gc();
        return c=='M'; 
    }
    void adde(int u,int v){
        E[o]=(Edge){v,hd[u]};hd[u]=o++;
        E[o]=(Edge){u,hd[v]};hd[v]=o++;
    }
    void dfs1(int u,int F){
        sz[u]=1;sn[u]=0;
        f[u]=w[u];
        for(int i=hd[u];~i;i=E[i].nt){
            int v=E[i].v;
            if(v==F)continue;
            dfs1(v,u);
            fa[v]=u;
            sz[u]+=sz[v];
            f[u]+=f[v];
            if(sz[v]>sz[sn[u]])sn[u]=v;
            if(h[u]<h[v])h[u]=h[v];
        }
        if(f[u]<0)f[u]=0;
        if(h[u]<f[u])h[u]=f[u];
    }
    void dfs2(int u,int T){
        tp[u]=T;
        id[st[u]=++idx]=u;
        if(sn[u])dfs2(sn[u],T),ed[u]=ed[sn[u]];
        else ed[u]=idx;
        g[u]=w[u];
        for(int i=hd[u];~i;i=E[i].nt){
            int v=E[i].v;
            if(v==fa[u]||v==sn[u])continue;
            dfs2(v,v);
            g[u]+=f[v]; 
            q[u].push(h[v]);
        }
    }
    void init(int k,int l){
        ss[k]=g[id[l]];
        mx[k]=q[id[l]].top();
        s[k]=sl[k]=sr[k]=max(g[id[l]],0ll);
    }
    void pushup(int k){
        mx[k]=max(mx[ls],mx[rs]);
        s[k]=max(max(s[ls],s[rs]),sr[ls]+sl[rs]);
        sl[k]=max(sl[ls],ss[ls]+sl[rs]);
        sr[k]=max(sr[ls]+ss[rs],sr[rs]);
        ss[k]=ss[ls]+ss[rs];
    }
    void build(int k,int l,int r){
        if(l==r){init(k,l);return;}
        int mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(k);
    }
    void update(int k,int l,int r,int x){
        if(l==r){init(k,l);return;}
        int mid=(l+r)>>1;
        if(x<=mid)update(ls,l,mid,x);
        else update(rs,mid+1,r,x);
        pushup(k);
    }
    ll S,Sl,Sr,Mx,Ss;
    void query(int k,int l,int r,int x,int y){
        if(l==x&&r==y){
            Mx=max(Mx,mx[k]);
            S=max(max(S,s[k]),Sr+sl[k]);
            Sl=max(Sl,Ss+sl[k]);
            Sr=max(Sr+ss[k],sr[k]);
            Ss=Ss+ss[k];
            return ;
        }
        int mid=(l+r)>>1;
        if(y<=mid)query(ls,l,mid,x,y);
        else if(x>mid)query(rs,mid+1,r,x,y);
        else query(ls,l,mid,x,mid),query(rs,mid+1,r,mid+1,y);
    }
    void Update(int x,int y){
        int tx=tp[x];
        g[x]-=w[x];g[x]+=(w[x]=y);
        while(tx!=1){
            update(1,1,n,st[x]);
            S=Sl=Sr=Ss=Mx=0;
            query(1,1,n,st[tx],ed[tx]);
            if(Sl!=f[tx]){
                g[fa[tx]]-=f[tx];
                g[fa[tx]]+=(f[tx]=Sl);
            }
            Mx=max(Mx,S);
            if(h[tx]!=Mx){
                q[fa[tx]].pop(h[tx]);
                q[fa[tx]].push(h[tx]=Mx);
            }
            x=fa[tx],tx=tp[x];
        }
        update(1,1,n,st[x]);
    }
    void Query(int x){
        S=Sl=Sr=Ss=Mx=0;
        query(1,1,n,st[x],ed[x]);
        Mx=max(Mx,S);
        printf("%lld
    ",Mx);
    }
    int main(){
    //    freopen("bzoj5210.in","r",stdin);
    //    freopen("bzoj5210.out","w",stdout);
        n=rd();m=rd();
        for(int i=1;i<=n;++i)hd[i]=-1,w[i]=rd();
        for(int i=1;i<n;++i)adde(rd(),rd());
        dfs1(1,0);
        dfs2(1,1);
        build(1,1,n);
        for(int i=1,x,y;i<=m;++i){
            if(gt())x=rd(),y=rd(),Update(x,y);
            else x=rd(),Query(x);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    生成不带签名(BOM)的UTF8格式的XML
    矢量数据的裁剪及合并
    使用dotNET_Reactor4.7加密后的dll在VS2010中无法打包
    加密后的程序在Win8中无法运行
    修改jpg的图片大小
    shapefile中dbf的数据格式(转载)
    shapefile 输出的地理处理注意事项(转载)
    linxu下面的绝对路径和相对路径
    go中的类型转换成interface之后如何复原
    使用docker部署一个go应用
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10415622.html
Copyright © 2020-2023  润新知