Slope Optimization + Tree Division treatment.
Point division: Find the center of gravity of the current subtree, divide the root to the center of gravity This section, update the value of the root to the center of gravity, the remaining points can be reached by the height from low to high order, update. Divide and conquer other sub-trees.
#include <cstdio>#include<algorithm>#include<cstring>#defineLL Long Longusing namespacestd;Const intMAXN =400000+Ten;Const intMAXM =400000+Ten;intG[maxn],v[maxn],next[maxn],eid; LL W[MAXN];intn,m,tot,root,t; LL F[MAXN],D[MAXN],P[MAXN],Q[MAXN],LIM[MAXN];intFA[MAXN],MS[MAXN],SIZE[MAXN];intseq[maxn],cnt;intstack[maxn],sp;DoubleK[MAXN];BOOLMARK[MAXN];voidAddedge (intAintb,ll C) {V[eid]=b; W[eid]=c; Next[eid]=g[a]; g[a]=eid++; }voidDfsintu) { for(intI=g[u];~i;i=Next[i]) {D[v[i]]=d[u]+W[i]; DFS (V[i]); }}void Get(intu) {Ms[u]=0; size[u]=1; for(intI=g[u];~i;i=next[i])if(!Mark[i]) { Get(V[i]); Size[u]+=Size[v[i]]; Ms[u]=Max (Ms[u],size[v[i]]); } Ms[u]=max (ms[u],tot-Size[u]); if(Ms[u]<ms[root]) root=u;}DoubleSlopeintXinty) {return(Double) (F[x]-f[y])/(Double) (d[x]-D[y]); }voidUpdateintXinty) {if(d[x]-d[y]<=lim[x]) f[x]=min (f[x],f[y]+ (d[x]-d[y]) *p[x]+q[x]); }voidVisitintu) {seq[++cnt]=u; for(intI=g[u];~i;i=Next[i])if(!Mark[i]) visit (v[i]);}voidInsertintx) { while(sp>1&& slope (X,STACK[SP]) >slope (stack[sp],stack[sp-1])) sp--; stack[++sp]=x; K[sp]=-slope (x,stack[sp-1]);}BOOLcmpintXinty) {returnd[x]-lim[x]>d[y]-lim[y];}voidSolveintu) {if(tot<=1)return; Root=0;Get(U); inttmp=Root; for(intI=g[fa[tmp]];~i;i=next[i])if(!mark[i]&&v[i]==tmp) {Mark[i]=1; Tot=size[u]-size[v[i]]; Solve (U); Break; } for(intI=fa[tmp];i!=fa[u];i=fa[i]) update (tmp,i); CNT=0; for(intI=g[tmp];~i;i=next[i])if(!Mark[i]) visit (V[i]); Sort (Seq+1, seq+cnt+1, CMP); SP=0; for(intI=1, j=tmp;i<=cnt;i++) { inty=Seq[i]; for(; j!=fa[u]&&d[j]>=d[y]-lim[y];j=Fa[j]) Insert (j); if(!SP)Continue; Else if(sp==1) Update (Y,STACK[SP]); ElseUpdate (Y,stack[min (SP, (int) (Upper_bound (k +2, k+sp+1,-p[y])-k-1))]); } for(intI=g[tmp];~i;i=next[i])if(!Mark[i]) {Mark[i]=1; tot=Size[v[i]]; solve (v[i]); }}intMain () {memset (g,-1,sizeof(g)); scanf ("%d%d",&n,&t); ms[0]=1000000000; for(intI=2, x,y;i<=n;i++) {scanf ("%d%d%lld%lld%lld",&fa[i],&y,&p[i],&q[i],&Lim[i]); Addedge (Fa[i],i,y); F[i]=1ll<< +; } DFS (1); tot=N; Solve (1); for(intI=2; i<=n;i++) printf ("%lld\n", F[i]); return 0;}
bzoj3672: [Noi2014] Buy Tickets