zoukankan      html  css  js  c++  java
  • 题解 洛谷 P4292 【[WC2010]重建计划】

    先二分答案 (mid),使得 $frac{val}{tot} geqslant mid $,移项得:

    [large val - tot imes mid geqslant 0 ]

    判定对每条边的边权都减去 (mid) 后,是否存在一条边权和大于零的路径即可。

    考虑树形 (DP),设 (f_{x,i}) 为以 (x) 为根的子树内,从 (x) 向下延伸 (i) 条边所形成的路径边权和的最大值,直接 (DP) 复杂度是 (O(n^2)) 的,无法接受。

    发现状态是和深度有关,所以考虑用长链剖分来优化,每次转移时,先从重儿子继承过来,然后再将轻儿子合并,合并轻儿子时扫一遍轻儿子所在的链即可。因为每个轻儿子都是其所在链的顶端,所以每个点都只会被扫一次,复杂度就有保证了。

    因为有边数的限制,所以合并时用线段树来维护。长链剖分后进行 (dfs),优先遍历重儿子,求出 (dfs) 序。对于 (DP) 状态 (f_{x,i}),将其用 (dfn_x + i) 在线段树上表示,这样每个状态都有一个对应的表示,转移时也便于合并,链上的信息为一个连续的区间,重儿子能直接转移到当前节点。

    #include<bits/stdc++.h>
    #define maxn 200010
    #define maxm 800010
    #define inf 2000000000000000
    #define ls (cur<<1)
    #define rs (cur<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,L,R,cnt,root=1;
    double now,ans,l,r;
    int d[maxn],dep[maxn],len[maxn],son[maxn],dfn[maxn];
    double val[maxn],dis[maxn],t[maxn],mx[maxm];
    struct edge
    {
        int to,nxt;
        double v;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to,double val)
    {
        e[++edge_cnt]=(edge){to,head[from],val};
        head[from]=edge_cnt,r=max(r,val);
    }
    void modify(int l,int r,int pos,double v,int cur)
    {
        if(l==r)
        {
            mx[cur]=max(mx[cur],v);
            return;
        }
        if(pos<=mid) modify(l,mid,pos,v,ls);
        else modify(mid+1,r,pos,v,rs);
        mx[cur]=max(mx[ls],mx[rs]);
    }
    double query(int L,int R,int l,int r,int cur)
    {
        if(L>R) return -inf;
        if(L<=l&&R>=r) return mx[cur];
        double v=-inf;
        if(L<=mid) v=max(v,query(L,R,l,mid,ls));
        if(R>mid) v=max(v,query(L,R,mid+1,r,rs));
        return v;
    }
    void clear(int l,int r,int cur)
    {
        mx[cur]=-inf;
        if(l==r) return;
        clear(l,mid,ls),clear(mid+1,r,rs);
    }
    void dfs_son(int x,int fa)
    {
        d[x]=dep[x]=d[fa]+1;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(y==fa) continue;
            dfs_son(y,x),dep[x]=max(dep[x],dep[y]);
            if(dep[y]>dep[son[x]]) son[x]=y,val[son[x]]=e[i].v;
        }
        len[x]=dep[x]-d[x];
    }
    void dfs_dfn(int x)
    {
        dfn[x]=++cnt;
        if(son[x]) dfs_dfn(son[x]);
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(dfn[y]) continue;
            dfs_dfn(y);
        }
    }
    void dp(int x,int fa)
    {
        modify(1,n,dfn[x],dis[x],root);
        if(son[x]) dis[son[x]]=dis[x]+val[son[x]]-now,dp(son[x],x);
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(y==fa||y==son[x]) continue;
            dis[y]=dis[x]+e[i].v-now,dp(y,x);
            for(int j=1;j<=len[y]+1;++j) t[j]=query(dfn[y]+j-1,dfn[y]+j-1,1,n,root);
            for(int j=1;j<=min(len[y]+1,R);++j)
                ans=max(ans,t[j]+query(dfn[x]+L-j,min(dfn[x]+R-j,dfn[x]+len[x]),1,n,root)-2*dis[x]);
            for(int j=1;j<=len[y]+1;++j) modify(1,n,dfn[x]+j,t[j],root);
        }
        ans=max(ans,query(dfn[x]+L,min(dfn[x]+R,dfn[x]+len[x]),1,n,root)-dis[x]);
    }
    bool check(double m)
    {
        now=m,ans=-inf,clear(1,n,root),dp(1,0);
        return ans>=0;
    }
    int main()
    {
        read(n),read(L),read(R);
        for(int i=1;i<n;++i)
        {
            int x,y,v;
            read(x),read(y),read(v);
            add(x,y,v),add(y,x,v);
        }
        dfs_son(1,0),dfs_dfn(1);
        for(int i=1;i<=35;++i)
        {
            double m=(l+r)/2;
            if(check(m)) l=m;
            else r=m;
        }
        printf("%.3lf",l);
        return 0;
    }
    
  • 相关阅读:
    CSS总结(六)——元素的垂直居中(已知高度/未知高度)
    CSS总结(五)——定位 position
    CSS总结(四)—— CSS选择器优先级
    CSS总结(三)—— 盒子模型(标准/IE下)
    CSS总结(二)—— 浮动 与 清除浮动
    CSS总结(一)—— display三种元素(区别、重点、扩展)
    JavaScript学习笔记(九)—— JS 理解闭包
    严格模式use strict
    let、const和var的区别
    字符串方法
  • 原文地址:https://www.cnblogs.com/lhm-/p/13493208.html
Copyright © 2011-2022 走看看