感觉是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.
View Code

 

posted on 2015-06-20 16:18  acphile  阅读(216)  评论(0编辑  收藏  举报