zoukankan      html  css  js  c++  java
  • BZOJ1767 : [Ceoi2009]harbingers

    设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>
    #define N 100010
    typedef long long ll;
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    int n,i,x,y,z,g[N],nxt[N<<1],v[N<<1],w[N<<1],ok[N<<1],ed=1,son[N],f[N],size,now,fa[N],V[N];
    int q[N],anc[N],t,ta;
    ll ans[N],d[N],W[N];
    inline void add(int x,int y,int 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 deal(int x){
      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;
      }
      up(ans[x],W[x]+ans[q[fin]]-d[q[fin]]*V[x]);
    }
    void dfs(int x){
      W[x]+=d[x]*V[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){
      deal(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){
      up(ans[x],W[x]+ans[y]-d[y]*V[x]);
      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(ta=0,i=fa[rt];;i=fa[i]){
          anc[++ta]=i;
          if(i==x)break;
        }
        for(t=0;ta;q[++t]=anc[ta--])while(t>1&&pos(anc[ta],q[t])<pos(q[t],q[t-1]))t--;
        if(rt>1)deal(rt);
        while(t>1&&pos(rt,q[t])<pos(q[t],q[t-1]))t--;
        q[++t]=rt;
        for(i=g[rt];i;i=nxt[i])if(ok[i])cal(v[i],rt);
        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(){
      read(n);
      for(i=1;i<n;i++)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
      for(i=2;i<=n;i++)read(x),read(V[i]),W[i]=x,ans[i]=1LL<<60;
      son[1]=n,dfs(1),solve(1);
      for(i=2;i<=n;i++)printf(i<n?"%lld ":"%lld",ans[i]);
      return 0;
    }
    

      

  • 相关阅读:
    Yield Usage Understanding
    Deadclock on calling async methond
    How to generate file name according to datetime in bat command
    Run Unit API Testing Which Was Distributed To Multiple Test Agents
    druid的关键参数+数据库连接池运行原理
    修改idea打开新窗口的默认配置
    spring boot -thymeleaf-url
    @pathvariable和@RequestParam的区别
    spring boot -thymeleaf-域对象操作
    spring boot -thymeleaf-遍历list和map
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403158.html
Copyright © 2011-2022 走看看