Description
Input
Output
Sample Input
3
1 1
1 2
2 2
Sample Output
8.0000
Data Constraint
题解
我还挺喜欢数学的呢
这题一眼看上去不会,化化式子没想到未知数竟然是一个反比例+一次函数的样子。
长这样:
a
x
+
b
x
\frac a x+bx
xa+bx
当时心态就没了。
原来这玩意是一个在高中叫做双勾函数(或对勾函数或耐克函数)
很好,于是我们就看看这个玩意长什么样——
既然是长这个样子,那么应该就有一个顶点(最小点)。
利用均值不等式可以得到——
(
a
b
a
,
2
a
b
)
(\frac{\sqrt{ab}}a,2\sqrt{ab})
(aab,2ab)
由于图中有很多很多的双勾函数,那么其中必然有一些线没有用的。
我们考虑删去这些没有用的
怎么删?
首先我们对于任意两点——满足
a
i
<
a
j
且
y
i
<
y
j
(
答
案
)
a_i<a_j且y_i<y_j(答案)
ai<aj且yi<yj(答案)
那么
a
i
+
b
i
+
a
i
∗
x
+
b
i
x
<
a
j
+
b
j
+
a
j
∗
x
+
b
j
x
a_i+b_i+a_i*x+\frac{b_i}{x}<a_j+b_j+a_j*x+\frac{b_j}{x}
ai+bi+ai∗x+xbi<aj+bj+aj∗x+xbj
化一波式子得到:
x
>
b
i
−
b
j
a
j
−
a
i
x>\frac{b_i-b_j}{a_j-a_i}
x>aj−aibi−bj
设
c
[
i
,
j
]
=
b
i
−
b
j
a
j
−
a
i
c[i,j]=\frac{b_i-b_j}{a_j-a_i}
c[i,j]=aj−aibi−bj
则我们对于一个
c
[
i
,
j
]
>
c
[
j
,
k
]
c[i,j]>c[j,k]
c[i,j]>c[j,k]那么j这个点就是没有用的。
所以说,我们就得到一个序列
d
d
d,序列满足
c
[
d
i
−
1
,
d
i
]
<
c
[
d
i
,
d
i
+
1
]
c[d_{i-1},d_i]<c[d_i,d_{i+1}]
c[di−1,di]<c[di,di+1]
这个东东是递增的。
那么我们发现:当
x
x
x在
c
[
d
i
−
1
,
d
i
]
c[d_{i-1},d_i]
c[di−1,di]到
c
[
d
i
,
d
i
+
1
]
c[d_i,d_{i+1}]
c[di,di+1]这段区间内时,
d
i
d_i
di的函数值是最大的。
因此,我们在
d
i
d_i
di的函数上判断这段区间的最小值即可。
怎么判断?可能有三种情况:
1、在顶点左边。
2、在顶点右边。
3、横跨顶点。
O ( n ) O(n) O(n)求即可。
代码
var
i,j,k,l,n,m,now:longint;
a,b,d:array[0..1000003] of longint;
op,oq,x,y,ans,aa,bb:extended;
function min(x,y:extended):extended;
begin
if x<y then exit(x);exit(y);
end;
procedure qsort(l,r:longint);
var
i,j,m,m1:longint;
begin
i:=l;j:=r;
m:=a[(l+r) div 2];
m1:=b[(l+r) div 2];
repeat
while (a[i]<m) or ((a[i]=m) and (b[i]<m1)) do inc(i);
while (a[j]>m) or ((a[j]=m) and (b[j]>m1)) do dec(j);
if i<=j then
begin
a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
b[0]:=b[i];b[i]:=b[j];b[j]:=b[0];
inc(i);dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if r>i then qsort(i,r);
end;
function pd(i:longint):boolean;
var
x,y,op,oq:extended;
begin
x:=b[d[now]]-b[d[now-1]];
y:=a[d[now-1]]-a[d[now]];
op:=x/y;
x:=b[i]-b[d[now]];
y:=a[d[now]]-a[i];
oq:=x/y;
if op>oq then exit(true);
exit(false);
end;
begin
//assign(input,'monster.in');reset(input);
readln(n);
for i:=1 to n do
begin
read(a[i],b[i]);
end;
qsort(1,n);
now:=1;
d[1]:=1;
for i:=2 to n do
begin
if a[i]>a[1] then
begin
inc(now);
d[now]:=i;
j:=i;
break;
end;
end;
for i:=j+1 to n do
begin
if a[i]>a[d[now]] then
begin
while (now>=2) and (pd(i)) do dec(now);
inc(now);d[now]:=i;
end;
end;
ans:=maxlongint;
for i:=2 to now-1 do
begin
x:=b[d[i]]-b[d[i-1]];
y:=a[d[i-1]]-a[d[i]];
op:=x/y;
x:=b[d[i+1]]-b[d[i]];
y:=a[d[i]]-a[d[i+1]];
oq:=x/y;
aa:=a[d[i]];
bb:=b[d[i]];
if op>sqrt(aa*bb)/aa then ans:=min(ans,aa*op+bb/op+aa+bb);
if oq<sqrt(aa*bb)/aa then ans:=min(ans,aa*oq+bb/oq+aa+bb);
if (op<=sqrt(aa*bb)/aa) and (oq>=sqrt(aa*bb)/aa) then ans:=min(ans,2*sqrt(aa*bb)+aa+bb);
end;
x:=b[d[now]]-b[d[now-1]];
y:=a[d[now-1]]-a[d[now]];
aa:=a[d[now]];bb:=b[d[now]];
op:=x/y;
if op>sqrt(aa*bb)/aa then ans:=min(ans,aa*op+bb/op+aa+bb)
else ans:=min(ans,2*sqrt(aa*bb)+aa+bb);
writeln(ans:0:4);
end.