感觉是noi2014中最有价值的一道题了
我们先考虑链上这个问题怎么做……
如果没限制,那就是SB的斜率优化
我们可以得到这个式子(f[j]-f[k])/(s[j]-s[k])<p[i]
点横坐标是单调的,我们只要维护凸壳然后二分即可
有距离限制?好像不好弄,不过我们记得cash那道坐标不单调的题我们是可以用cdq分治的
这道题也一样,划分,考虑左半部分对右半部分的影响
我们只要对右半部分距离限制排序然后依次加点维护凸壳然后二分即可
换到树上来那就是点分治啦,
我们找重心,先做重心子树外(就是包含根的那部分),做完之后
考虑重心的祖先对子树的影响,我们完全可以如法炮制
然后不断向下递归处理即可
这样noi2014的传统题就做完啦!
1 const inf=9223372036854775807; 2 eps=1e-10; 3 4 type node=record 5 po,next:longint; 6 end; 7 point=record 8 x,y:int64; 9 end; 10 11 var h,fp,p,fa,mx,s,q,b:array[0..200010] of longint; 12 a:array[0..200010] of point; 13 cut:array[0..200010] of boolean; 14 e:array[0..200010] of node; 15 w,f,d,kp,bp,lim:array[0..200010] of int64; 16 x,t,i,len,n,ty,r:longint; 17 18 function max(a,b:longint):longint; 19 begin 20 if a>b then exit(a) else exit(b); 21 end; 22 23 procedure min(var a:int64; b:int64); 24 begin 25 if a>b then a:=b; 26 end; 27 28 procedure add(x,y:longint); 29 begin 30 inc(len); 31 e[len].po:=y; 32 e[len].next:=p[x]; 33 p[x]:=len; 34 end; 35 36 procedure bfs(st:longint); 37 var i,f,x,y:longint; 38 begin 39 f:=1; 40 r:=1; 41 q[1]:=st; 42 while f<=r do 43 begin 44 x:=q[f]; 45 i:=p[x]; 46 while i<>0 do 47 begin 48 if not cut[i] then 49 begin 50 inc(r); 51 q[r]:=e[i].po; 52 end; 53 i:=e[i].next; 54 end; 55 inc(f); 56 end; 57 end; 58 59 procedure swap(var a,b:longint); 60 var c:longint; 61 begin 62 c:=a; 63 a:=b; 64 b:=c; 65 end; 66 67 function cmp(i,j:longint):boolean; 68 begin 69 exit(lim[i]-d[i]<lim[j]-d[j]); 70 end; 71 72 procedure sort(l,r:longint); 73 var i,j,x:longint; 74 begin 75 i:=l; 76 j:=r; 77 x:=b[(l+r) shr 1]; 78 repeat 79 while cmp(b[i],x) do inc(i); 80 while cmp(x,b[j]) do dec(j); 81 if i<=j then 82 begin 83 swap(b[i],b[j]); 84 inc(i); 85 dec(j); 86 end; 87 until i>j; 88 if l<j then sort(l,j); 89 if i<r then sort(i,r); 90 end; 91 92 function getk(i,j:longint):extended; 93 begin 94 exit((a[i].y-a[j].y)/(a[i].x-a[j].x)); 95 end; 96 97 function find(l,r,x:longint):longint; 98 var m:longint; 99 s1,s2:int64; 100 begin 101 while l<r do 102 begin 103 m:=(l+r) shr 1; 104 s1:=a[h[m]].y+a[h[m]].x*kp[x]; 105 s2:=a[h[m+1]].y+a[h[m+1]].x*kp[x]; 106 if s1>s2 then l:=m+1 107 else r:=m; 108 end; 109 exit(h[l]); 110 end; 111 112 procedure cdq(root:longint); 113 var i,j,x,mid,m,y:longint; 114 begin 115 bfs(root); 116 if r=1 then exit; 117 mid:=0; 118 for i:=r downto 1 do 119 begin 120 x:=q[i]; 121 s[x]:=1; 122 mx[x]:=0; 123 j:=p[x]; 124 while j<>0 do 125 begin 126 y:=e[j].po; 127 if not cut[j] then 128 begin 129 s[x]:=s[x]+s[y]; 130 mx[x]:=max(mx[x],s[y]); 131 end; 132 j:=e[j].next; 133 end; 134 mx[x]:=max(mx[x],r-s[x]); 135 if mx[x]<mx[mid] then mid:=x; 136 end; 137 if root<>mid then 138 begin 139 cut[fp[mid]]:=true; 140 cdq(root); 141 m:=0; 142 x:=fa[mid]; 143 while x<>root do 144 begin 145 inc(m); 146 a[m].x:=-d[x]; //为了方便改变一下形式 147 a[m].y:=f[x]; 148 x:=fa[x]; 149 end; 150 inc(m); 151 a[m].x:=-d[x]; 152 a[m].y:=f[x]; 153 154 bfs(mid); 155 for i:=1 to r do 156 b[i]:=q[i]; 157 sort(1,r); 158 t:=0; 159 j:=1; 160 for i:=1 to r do 161 begin 162 x:=b[i]; 163 while (j<=m) and (a[j].x<=lim[x]-d[x]) do 164 begin 165 while (t>1) and (getk(j,h[t])-eps<getk(h[t],h[t-1])) do dec(t); 166 inc(t); 167 h[t]:=j; 168 inc(j); 169 end; 170 if t>0 then 171 begin 172 y:=find(1,t,x); 173 min(f[x],a[y].y+kp[x]*(d[x]+a[y].x)+bp[x]); 174 end; 175 end; 176 end; 177 for i:=2 to r do 178 begin 179 x:=q[i]; 180 if d[x]-d[mid]<=lim[x] then 181 min(f[x],f[mid]+kp[x]*(d[x]-d[mid])+bp[x]); 182 end; 183 i:=p[mid]; 184 while i<>0 do 185 begin 186 if not cut[i] then cdq(e[i].po); 187 i:=e[i].next; 188 end; 189 end; 190 191 begin 192 readln(n,ty); 193 for i:=2 to n do 194 begin 195 readln(fa[i],w[i],kp[i],bp[i],lim[i]); 196 add(fa[i],i); 197 fp[i]:=len; 198 f[i]:=inf; 199 end; 200 bfs(1); 201 for i:=2 to r do 202 begin 203 x:=q[i]; 204 d[x]:=d[fa[x]]+w[x]; 205 end; 206 mx[0]:=n+1; 207 f[1]:=0; 208 cdq(1); 209 for i:=2 to n do 210 writeln(f[i]); 211 end.