Test instructions
A root tree with n nodes is given, and the edge has a length;
Each point has its ancestors that can purchase tickets to the length of the difference does not exceed Li, the cost of the ticket is pi* length +qi;
Of course, you can select multiple reversing to arrive;
The minimum cost per point to root;
n<=200000;
Exercises
This question is really good, the data special situation gives you to give you a special sentence of 2333;
First the case of a chain will be, set f[i] for I to the minimum cost of the root, dis for the distance to the root;
The transfer equation is: f[i]=f[j]+p[i]* (Dis[i]-dis[j]) +q[i];
Slope optimization to engage in a good;
However, in the tree, and in the sequence of the idea is basically the same;
But a lot more details to deal with;
Divide and conquer nature is to divide, the point should be the center of gravity of the tree;
After the division?
The tree after the partition should be rooted, because the DP values of all the points are updated by the ancestors of the trees;
So we use this chain of roots to divide the center to update all the other sub-trees of the Division center;
But unlike the general sequence, we can not handle the convex package and then two points to find the answer;
That would have the optional value omitted;
So the points to be updated are placed in a sequence, sorted by the ancestor to which they are capable;
After sorting it in this sequence sweep is good, time complexity is O (L*LOGL);
Then with the complexity of the tree partition, the total complexity O (nlog^2n);
A lot of details, the tree divided the posture are not familiar with it;
Code:
#include <stdio.h> #include <string.h> #include <algorithm> #define N 210000using namespace std; typedef long LONG Ll;int next[n],to[n],head[n],tot;ll val[n];int fa[n],size[n],st[n],top,qu[n],s,t,g,mi;ll P[N],q[N], L[n],dis[n],f[n];bool ban[n];void Add (int x,int y,ll v) {To[++tot]=y;val[tot]=v;next[tot]=head[x];head[x]=tot;} void init (int x) {size[x]=1;for (int i=head[x];i;i=next[i]) {dis[to[i]]=dis[x]+val[i];init (to[i]); size[x]+=size[to[i ]];}} BOOL CMP (int a,int b) {return dis[a]-l[a]>dis[b]-l[b];} void Getp (int x) {st[++top]=x;for (int i=head[x];i;i=next[i]) if (!ban[to[i]]) GETP (To[i]);} ll find (int x) {if (s>t) return 0x3f3f3f3f3f3f3f3fll;int l=s,r=t,mid;while (l<=r) {mid=l+r>>1;if (mid+1>t || (Long Double) (F[qu[mid+1]]-f[qu[mid]])/(Dis[qu[mid+1]]-dis[qu[mid]]) <p[x]) r=mid-1;elsel=mid+1; Return f[qu[l]]+p[x]* (Dis[x]-dis[qu[l]]) +q[x];} void Getg (int x,int bk) {size[x]=1;int i,mas=0,temp;for (I=head[x];i;i=next[i]) {if (Ban[to[i]]) CONTINUE;GETG (TO[I],BK ); size[x]+=size[to[i]];mas=mAx (Mas,size[to[i]]);} Mas=max (mas,bk-size[x]); if (Mas<=mi) mi=mas,g=x;} void Slove (int x,int y) {if (size[x]==1) return; int i,j,k;for (i=head[y];i;i=next[i]) if (!ban[to[i]]) ban[to[i]]=1;mi= 0X3F3F3F3F;GETG (X,size[x]); Slove (x,g); Top=0;for (I=head[y];i;i=next[i]) GETP (to[i]); sort (st+1,st+top+1,cmp); S=1, T=0;for (i=1,k=y;i<=top;i++) {while (K!=fa[x]&&dis[st[i]]-l[st[i]]<=dis[k]) {while (s<t&& ( Long double) (f[qu[t-1]]-f[qu[t])/(Dis[qu[t-1]]-dis[qu[t]) < (long double) (f[qu[t]]-f[k])/(Dis[qu[t]]-dis[k])) T--;QU[++T]=K;K=FA[K];} F[st[i]]=min (F[st[i]],find (St[i));} for (I=head[y],k=size[x];i;i=next[i]) {MI=0X3F3F3F3F;GETG (to[i],size[to[i]); Slove (to[i],g);}} int main () {int n,m,i,j,k,x,y;ll v;scanf ("%d%d", &n,&m), for (i=2;i<=n;i++) {scanf ("%d%lld%lld%lld%lld", fa+ I,&v,p+i,q+i,l+i); add (fa[i],i,v);} Ban[1]=0;init (1); Memset (F,0x3f,sizeof (f)); F[1]=0;mi=0x3f3f3f3f;getg (1,size[1]); Slove (1,g); for (i=2;i<=n;i++) printf ("%lld\n", F[i]); return 0;}
bzoj-3672 Ticket Purchase