zoukankan      html  css  js  c++  java
  • BZOJ3672 : [Noi2014]购票

    设d[i]表示i到1的距离

    f[i]=w[i]+min(f[j]+(d[i]-d[j])*v[i])=w[i]+d[i]*v[i]+min(-d[j]*v[i]+f[j])

    对这棵树进行点分治,每次递归时的根为x,重心为rt

    如果x==rt,则把树中所有点用x暴力更新,然后递归分治

    否则,先递归分治x的那部分子树,将树中每个点按照能走到的最远处的深度从大到小排序

    然后将rt到x路径上所有点维护一个凸壳,依次加入直线

    对于树中每一个点,在凸壳上二分更新答案

    最后再递归分治其它子树

    #include<cstdio>
    #include<algorithm>
    #define N 200010
    typedef long long ll;
    int n,i,x,g[N],nxt[N<<1],v[N<<1],ok[N<<1],ed=1,son[N],f[N],size,now,fa[N];
    int q[N],all[N],t,cnt;
    ll w[N<<1],ans[N],d[N],W[N],V[N],lim[N],z;
    inline bool cmp(int x,int y){return lim[x]<lim[y];}
    inline void add(int x,int y,ll z){v[++ed]=y,w[ed]=z,nxt[ed]=g[x],ok[ed]=1,g[x]=ed;}
    inline void up(ll&x,ll y){if(x>y)x=y;}
    inline double pos(int x,int y){return (double)(ans[y]-ans[x])/(double)(d[y]-d[x]);}
    void findroot(int x,int pre){
      son[x]=1;f[x]=0;
      for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=pre){
        findroot(v[i],x),son[x]+=son[v[i]];
        if(son[v[i]]>f[x])f[x]=son[v[i]];
      }
      if(size-son[x]>f[x])f[x]=size-son[x];
      if(f[x]<f[now])now=x;
    }
    inline void use(int x,int y){if(d[y]>=lim[x])up(ans[x],W[x]+ans[y]-d[y]*V[x]);}
    inline void deal(int x){
      if(!t)return;
      int l=1,r=t-1,fin=t,mid;
      while(l<=r){
        mid=(l+r)>>1;
        if((double)V[x]>=pos(q[mid],q[mid+1]))r=(fin=mid)-1;else l=mid+1;
      }
      use(x,q[fin]);
    }
    void dfs(int x){
      W[x]+=d[x]*V[x];lim[x]=d[x]-lim[x];
      for(int i=g[x];i;i=nxt[i])if(v[i]!=fa[x])d[v[i]]=d[fa[v[i]]=x]+w[i],dfs(v[i]);
    }
    void cal(int x,int pre){
      all[++cnt]=x;
      for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=pre)cal(v[i],x);
    }
    void cal2(int x,int y){
      use(x,y);
      for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=fa[x])cal2(v[i],y);
    }
    void solve(int x){
      f[0]=size=son[x],findroot(x,now=0);
      int rt=now,i;
      if(rt!=x){
        for(i=g[rt];i;i=nxt[i])if(v[i]==fa[rt]){ok[i]=ok[i^1]=0,solve(x);break;}
        for(cnt=t=0,i=g[rt];i;i=nxt[i])if(ok[i])cal(v[i],rt);
        for(std::sort(all+1,all+cnt+1,cmp),i=fa[rt];i!=fa[x];i=fa[i])use(rt,i);
        for(i=rt;cnt;deal(all[cnt--]))for(;i!=fa[x];i=fa[i])if(d[i]>=lim[all[cnt]]){
          while(t>1&&pos(i,q[t])>pos(q[t],q[t-1]))t--;
          q[++t]=i;
        }else break;
        for(i=g[rt];i;i=nxt[i])if(ok[i])ok[i^1]=0,solve(v[i]);
      }else for(i=g[x];i;i=nxt[i])if(ok[i])ok[i^1]=0,cal2(v[i],x),solve(v[i]);
    }
    int main(){
      scanf("%d%d",&n,&i);
      for(i=2;i<=n;ans[i++]=1LL<<61)scanf("%d%lld%lld%lld%lld",&x,&z,&V[i],&W[i],&lim[i]),add(x,i,z),add(i,x,z);
      son[1]=n,dfs(1),solve(1);
      for(i=2;i<=n;i++)printf("%lld
    ",ans[i]);
      return 0;
    }
    

      

  • 相关阅读:
    Elasticsearch与kibana的单机安装
    PS 设计带斑点图案的背景
    中国传统纹样简略
    js 在非module中引用module里的变量和函数
    ssh 使用pem秘钥文件登录
    jquery sortable 使用注意事项
    ES6中的函数、对象定义
    file-loader返回object Module 路径的问题
    Louvain 论文笔记
    基于Docker方式的LNMP环境搭建
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403157.html
Copyright © 2011-2022 走看看