zoukankan      html  css  js  c++  java
  • 并不对劲的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 
    */
    
  • 相关阅读:
    javascript入门篇(一)
    vue开发项目详细教程(第一篇 搭建环境篇)
    node基础03:使用函数
    node基础02:第一个node程序
    node基础01:简要介绍
    mac基本用法
    ES5基础01:正则表达式
    php基础11:运算符
    H5(一):使用formData对象模拟表单
    HTTP基础(一):如何使用浏览器network查看请求和响应的信息
  • 原文地址:https://www.cnblogs.com/xzyf/p/10490462.html
Copyright © 2011-2022 走看看