Use the line tree to optimize the convex hull.
Note the following:
1. Recursive non-duplicated son must be performed first. If recursive re-son is performed first, a useful solution may be kicked out.
2. You cannot create only one Convex Hull for each chain, because the convex hull cannot be updated with only a certain part of the answer (it may not be considered that the point in the range is combined with a certain point to kill the optimal point ).
Another is to use double to compare the slope in the old field. Otherwise, long will be cracked.
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <vector> 6 using namespace std; 7 const long long INF=(long long)1e18; 8 const int maxn=200010; 9 int cnt,fir[maxn],to[maxn],nxt[maxn],son[maxn],sz[maxn],fa[maxn],n,t; 10 long long val[maxn],P[maxn],Q[maxn],S[maxn],F[maxn],L[maxn]; 11 void addedge(int a,int b,long long c){ 12 nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;val[cnt]=c; 13 } 14 15 void DFS(int x){ 16 sz[x]=1; 17 for(int i=fir[x];i;i=nxt[i]) 18 if(to[i]!=fa[x]){ 19 fa[to[i]]=x; 20 S[to[i]]=S[x]+val[i]; 21 DFS(to[i]); 22 sz[x]+=sz[to[i]]; 23 if(sz[son[x]]<sz[to[i]]) 24 son[x]=to[i]; 25 } 26 } 27 28 int top[maxn],ID[maxn],RID[maxn],tot; 29 void DFS(int x,int tp){ 30 ID[x]=++tot;RID[tot]=x;top[x]=tp; 31 if(son[x])DFS(son[x],tp); 32 for(int i=fir[x];i;i=nxt[i]) 33 if(to[i]!=fa[x]&&to[i]!=son[x]) 34 DFS(to[i],to[i]); 35 } 36 37 struct Slope{ 38 vector<int>id; 39 void Insert(int x){ 40 int p=id.size()-1; 41 id.push_back(x); 42 while(true){ 43 if(p<=0)break; 44 if(1.0*(F[id[p]]-F[id[p-1]])/(S[id[p]]-S[id[p-1]])<1.0*(F[id[p+1]]-F[id[p]])/(S[id[p+1]]-S[id[p]]))break; 45 id.pop_back();id.pop_back();id.push_back(x);p--; 46 } 47 return; 48 } 49 50 long long Query(int p){ 51 int p1=-1,p2; 52 for(int i=20;i>=0;i--){ 53 p2=p1+(1<<i); 54 if(p2>=id.size()-1)continue; 55 if(1.0*(F[id[p2+1]]-F[id[p2]])/P[p]<=1.0*(S[id[p2+1]]-S[id[p2]])) 56 p1+=1<<i; 57 } 58 p1+=1; 59 return F[id[p1]]+(S[p]-S[id[p1]])*P[p]+Q[p]; 60 } 61 }slope[maxn<<2]; 62 63 long long Query(int x,int l,int r,int a,int b,int p){ 64 if(l>=a&&r<=b) 65 return slope[x].Query(p); 66 67 int mid=(l+r)>>1; 68 long long ret=INF; 69 if(a<=mid) 70 ret=Query(x<<1,l,mid,a,b,p); 71 if(mid<b) 72 ret=min(ret,Query(x<<1|1,mid+1,r,a,b,p)); 73 return ret; 74 } 75 76 void Insert(int x,int l,int r,int p){ 77 slope[x].Insert(p); 78 if(l==r)return; 79 int mid=(l+r)>>1; 80 if(mid>=ID[p]) 81 Insert(x<<1,l,mid,p); 82 else 83 Insert(x<<1|1,mid+1,r,p); 84 } 85 86 long long Get_ans(int p){ 87 int pos=fa[p]; 88 long long ret=INF; 89 while(pos){ 90 if(S[p]-L[p]>S[pos])break; 91 int p1=ID[top[pos]]-1; 92 for(int i=20;i>=0;i--) 93 if(p1+(1<<i)<ID[pos]&&S[RID[p1+(1<<i)]]<S[p]-L[p]) 94 p1+=1<<i; 95 ret=min(ret,Query(1,1,n,p1+1,ID[pos],p)); 96 pos=fa[top[pos]]; 97 } 98 return ret; 99 }100 101 void Solve(int x){102 F[x]=x==1?0:Get_ans(x);103 Insert(1,1,n,x);104 for(int i=fir[x];i;i=nxt[i])105 if(to[i]!=son[x])106 Solve(to[i]);107 if(son[x])108 Solve(son[x]); 109 return;110 }111 112 int main(){113 #ifndef ONLINE_JUDGE 114 freopen("ticket.in","r",stdin);115 freopen("ticket.out","w",stdout);116 #endif 117 scanf("%d%d",&n,&t);118 for(int i=2,a,b;i<=n;i++){119 scanf("%d%d%lld%lld%lld",&a,&b,&P[i],&Q[i],&L[i]);120 addedge(a,i,b*1ll);121 }122 123 DFS(1);124 DFS(1,1);125 126 Solve(1);127 for(int i=2;i<=n;i++)128 printf("%lld\n",F[i]);129 return 0;130 }
Data structure (tree link Division): noi2014 ticket purchase