Tree
Description
给出一棵有
N
个节点的树,从中选出
Data Constraint
N
<=
Solution
首先,有一个显然的结论,
C
的取值最多只有
然后,显然答案具有二分性,所以我们可以考虑二分答案
Ans
,倘若算出来的答案比二分的答案要大,则有
Ans
<
SK+1
, 整理得
Ans
<
S
-
即
Ans
<
∑Ki=1
(Sumi−Ans)
我们用
Sumi
表示第i条路径的点权和,用
Sumi
-
Ans
表示一条路径的权值。
此时左边已经和式子的值没有关系了,考虑用树形动态规划求式子右边的最大值,
用
Gi
和
Fi
分别表示以
i
为根的子树内路径权值和最大值 以及 必须有一条路径经过
但我们发现这样做的时间复杂度仍然很大,我们对
这样就能将
注:对于一个长度为
Code(Pascal)
var
t,lim,i,j,k,l,o,p,n,x,y:longint;
dq,fa,po:array[0..16000] of longint;
le,ans,mid,ri,bj:real;
be,ne,bc:array[0..32000] of longint;
bz:array[0..1060000] of boolean;
f,g:array[0..16000] of real;
function maxe(a,b:real):real;
begin
if a>b then exit(a)
else exit(b);
end;
procedure dg(o:longint;p:real);
var
i,l,k,u:longint;
lj,kk,kkk,uu:real;
begin
f[o]:=-maxlongint;
g[o]:=-maxlongint;
if (bc[be[o]]=fa[o]) and (ne[be[o]]=0) then
begin
f[o]:=dq[o]-p;
g[o]:=0;
exit;
end;
k:=be[o];
while k>0 do
begin
if bc[k]<>fa[o] then
begin
fa[bc[k]]:=o;
dg(bc[k],p);
end;
k:=ne[k];
end;
k:=be[o];
lj:=0;
kk:=-maxlongint;
kkk:=kk;
while k>0 do
begin
u:=bc[k];
if fa[o]<>u then
begin
lj:=lj+g[u];
uu:=f[u]-g[u];
if uu>kk then
begin
kkk:=kk;
kk:=uu;
end
else
if uu>kkk then kkk:=uu;
end;
k:=ne[k];
end;
f[o]:=lj+kk+dq[o];
if f[o]>lj then g[o]:=f[o] else g[o]:=lj;
if lj+kk+kkk+dq[o]+p>g[o] then g[o]:=lj+kk+kkk+dq[o]+p;
end;
procedure sjzl;
var
i,k:longint;
begin
for i:=1 to p do
begin
k:=random(p div 2)+1+p div 2;
po[0]:=po[i];
po[i]:=po[k];
po[k]:=po[0];
end;
end;
function pd(o:real):boolean;
var
i:longint;
begin
fa[1]:=-1;
dg(1,o);
if g[1]>=o then exit(true)
else exit(false);
end;
begin
randomize;
readln(n,lim);
for i:=1 to n do
read(dq[i]);
for i:=1 to n-1 do
begin
readln(x,y);
inc(o); ne[o]:=be[x];
be[x]:=o; bc[o]:=y;
inc(o); ne[o]:=be[y];
be[y]:=o; bc[o]:=x;
end;
readln(t);
p:=2;
po[1]:=0;
po[2]:=t;
for i:=1 to n do
if lim-1-dq[i]<=t then
if not(bz[lim-1-dq[i]]) then
begin
inc(p);
po[p]:=lim-1-dq[i];
bz[po[p]]:=true;
end;
bj:=n;
bj:=maxe(bj*lim/8,100000);
for i:=1 to 10 do
sjzl;
for i:=1 to p do
begin
for l:=1 to n do
dq[l]:=(dq[l]+po[i]) mod lim;
if pd(ans) then
begin
le:=ans;
ri:=bj;
while le+0.000001<ri do
begin
mid:=(le+ri)/2;
if pd(mid) then le:=mid
else ri:=mid;
end;
ans:=le;
end;
for l:=1 to n do
dq[l]:=(dq[l]-po[i]+lim) mod lim;
end;
writeln(ans:0:7);
end.