• 并不对劲的bzoj1758:p4292:[WC2010]重建计划


    题目大意

    (n)((nleq10^5))个点的一棵树,有边权(w),给定(l,r),求边数在([l,r])中的路径的平均边权的最大值

    题解

    二分答案,判断时将边权变成(w-mid),判断是否存在一条边权总和非负且边数在[l,r]的路径
    (f(i,j))表示从点(i)往下走(j)条边的边权总和最多是多少
    则有(f(i,j)=max_{vin son(i)}{f(v,j-1)+w(i,v)})
    (ans(i)=max_{vin son(i) , lleq k+j+1leq r}{f(v,k)+f(i,j)+w(i,v)})
    考虑长链剖分,将(f(i,j))存到(F(i,j)=dfn[i]+j)的位置
    需要注意的是,算完点(i)的长儿子后,需要将(F(i,1))(F(i,dep[i]))的值+(w(i,v))
    看上去常数比点分治小,事实上。。。

    代码
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define rep(i,x,y) for(register int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
    #define view(u,k) for(int k=fir[u];~k;k=nxt[k])
    #define maxn 100010 
    #define maxm (maxn<<1)
    #define F(x,y) (dfn[x]+y)
    #define inf (1e11)
    #define ls (u<<1)
    #define rs (u<<1|1)
    #define mi (L+R>>1)
    #define eps (1e-4)
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)&&ch!='-')ch=getchar();
        if(ch=='-')f=-1,ch=getchar();
        while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return x*f;
    }
    void write(int x)
    {
        if(x==0){putchar('0'),putchar('
    ');return;}
        int f=0;char ch[20];
        if(x<0)putchar('-'),x=-x;
        while(x)ch[++f]=x%10+'0',x/=10;
        while(f)putchar(ch[f--]);
        putchar('
    ');
        return;
    }
    int n,l,r,cnt,fir[maxn],nxt[maxm],v[maxm],son[maxn],fa[maxn],dfn[maxn],tim,dep[maxn];
    double toso[maxn],w[maxm],tr[maxn<<2],mk[maxn<<2],ans,fakeans,mid;
    inline void ade(int u1,int v1,int w1){w[cnt]=(double)w1,v[cnt]=v1,nxt[cnt]=fir[u1],fir[u1]=cnt++;}
    void getdep(int u)
    {
        view(u,k)if(v[k]!=fa[u])
        {
            fa[v[k]]=u,getdep(v[k]),dep[u]=max(dep[v[k]]+1,dep[u]);
            if(!son[u]||dep[v[k]]>dep[son[u]])son[u]=v[k],toso[u]=w[k];
        }
    }
    void getdfn(int u)
    {
        dfn[u]=++tim;
        if(son[u])getdfn(son[u]);
        view(u,k)if(v[k]!=fa[u]&&v[k]!=son[u])getdfn(v[k]);
    }
    inline void mark(int u,double k){if(tr[u]!=-inf)mk[u]+=k,tr[u]+=k;}
    inline void pd(int u){if(mk[u]==-inf){tr[ls]=tr[rs]=-inf,mk[ls]=mk[rs]=-inf,mk[u]=0;}if(mk[u]){mark(ls,mk[u]),mark(rs,mk[u]),mk[u]=0;}}
    void add(int u,int L,int R,int x,int y,double k)
    {
        if(y<L||R<x||y<x)return ;
        if(x<=L&&R<=y)return mark(u,k);
        pd(u);
        if(x<=mi)add(ls,L,mi,x,y,k);
        if(y>mi)add(rs,mi+1,R,x,y,k);
        tr[u]=max(tr[ls],tr[rs]);
    }
    void chg(int u,int L,int R,int x,double k)
    {
        if(x<L||R<x)return;
        if(x<=L&&R<=x){tr[u]=max(tr[u],k);return;}
        pd(u);
        if(x<=mi)chg(ls,L,mi,x,k);
        if(x>mi)chg(rs,mi+1,R,x,k);
        tr[u]=max(tr[ls],tr[rs]);
    }
    double ask(int u,int L,int R,int x,int y)
    {
        if(y<L||R<x||y<x)return -inf;
        if(x<=L&&R<=y)return tr[u];
        pd(u);
        double res=-inf;
        if(x<=mi)res=ask(ls,L,mi,x,y);
        if(y>mi)res=max(res,ask(rs,mi+1,R,x,y));
        return res;
    }
    double tmp[maxn];
    void getans(int u)
    {
        if(son[u])getans(son[u]),add(1,1,n,F(u,1),F(u,dep[u]),toso[u]-mid);
        if(fakeans>=0)return;
        chg(1,1,n,F(u,0),0);
        int Llim=max(0,l),Rlim=min(dep[u],r);
        if(Llim<=Rlim)
        {
            double tmp=ask(1,1,n,F(u,Llim),F(u,Rlim));
            fakeans=max(fakeans,tmp);
            if(fakeans>=0)return;
        }
        view(u,k)if(v[k]!=fa[u]&&v[k]!=son[u])
        {
            getans(v[k]);
            if(fakeans>=0)return;
            rep(i,0,dep[v[k]])
            {
                Llim=max(0,l-i-1),Rlim=min(r-i-1,dep[u]);
                tmp[i]=ask(1,1,n,F(v[k],i),F(v[k],i))+w[k]-mid;
                if(Llim<=Rlim)
                {	
                    double tmp2=ask(1,1,n,F(u,Llim),F(u,Rlim));
                    fakeans=max(fakeans,tmp2+tmp[i]);
                    if(fakeans>=0)return;
                }
            }
            rep(i,0,dep[v[k]])chg(1,1,n,F(u,i+1),tmp[i]);
        }
    }
    int main()
    {
        memset(fir,-1,sizeof(fir));
        n=read(),l=read(),r=read();double L=inf,R=0;
        rep(i,1,n-1){int x=read(),y=read(),z=read();ade(x,y,z),ade(y,x,z),L=min(L,(double)z),R=max(R,(double)z);}
        getdep(1),getdfn(1);
        while(R-L>=eps)
        {
            mid=(R+L)/2.0;
            fakeans=-inf;tr[1]=mk[1]=-inf;
            getans(1);
            if(fakeans>=0)ans=max(ans,mid),L=mid+eps;
            else R=mid-eps;
        }
        printf("%.3lf",ans);
        return 0;
    }
    /*
    4 
    2 3 
    1 2 1 
    1 3 2 
    1 4 3 
    */
    
  • 相关阅读:
    Java安全之JNDI注入
    Visual Studio 2019 升级16.8之后(升级.Net 5),RazorTagHelper任务意外失败
    .Net Core 3.1升级 .Net 5后出现代码错误 rzc generate exited with code 1.
    重走py 之路 ——普通操作与函数(三)
    重走py 之路 ——字典和集合(二)
    设计模式结(完结篇)
    重走py 之路 ——列表(一)
    RestfulApi 学习笔记——分页和排序(五)
    RestfulApi 学习笔记——查询与过滤还有搜索(五)
    Android开发 Error:The number of method references in a .dex file cannot exceed 64K.Android开发 Error:The number of method references in a .dex file cannot exceed 64K
  • 原文地址:https://www.cnblogs.com/xzyf/p/10490462.html
Copyright © 2020-2023  润新知