Codeforces Round #514 (Div. 2) D. Nature Reserve 多个二次函数的最大值是三分函数的证明

 

http://codeforces.com/contest/1059/problem/D

 

最大值:

最左下方和最右下方分别有一个点

r^2 - (r-1)^2 = (10^7)^2

maxr<0.5*10^14

 

Way1:

二分。

difference:

如果使用 5*10^13 -> 10^-6,2^ 60~70区间,pow,sqrt运算,实测超时。

实际上是,使用

time of a case:->

Code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+10;
 4 
 5 double x[maxn],y[maxn];
 6 double z=5.0*1e13;
 7 int n;
 8 
 9 bool work(double m)
10 {
11     double p,q,d;
12     int i;
13     p=-z; q=z;
14     for (i=1;i<=n;i++)
15     {
16         d=sqrt(pow(m,2)-pow(m-y[i],2));
17         p=max(p,x[i]-d);
18         q=min(q,x[i]+d);
19 //        if (p>q)
20 //            return 0;
21     }
22 //    return 1;
23     if (p<=q)
24         return 1;
25     else
26         return 0;
27 }
28 
29 int main()
30 {
31     double l=0,r,m;
32     int v,i;
33     scanf("%d",&n);
34     v=0;
35     for (i=1;i<=n;i++)
36     {
37         scanf("%lf%lf",&x[i],&y[i]);
38         if (y[i]!=0)
39         {
40             if (v==0)
41                 v=(y[i]>0);
42             else if (v!=(y[i]>0))
43             {
44                 printf("-1");
45                 return 0;
46             }
47         }
48         y[i]=fabs(y[i]);
49         l=max(l,y[i]/2);
50     }
51     r=z;
52     while ((r-l)/max(1.0,l)>1e-6)
53     {
54         m=(l+r)/2;
55         if (work(m))
56             r=m;
57         else
58             l=m;
59     }
60     printf("%.10f",r);
61     return 0;
62 }

 

Way2:

多个二次函数f1,f2,…,fn,ax^2+bx+c (a>0)

f(x)=max(f1(x),f2(x),…,fn(x)),

而f是先减小,后增大,使用三分法

 

证明:

设f(x)是由多个连续的二次函数片段组成,相邻的二次函数片段的斜率逐渐增大,而每个二次函数片段都是f''>0,所以当前f''>0

 

设加入新的函数后,变化的区间为

1.[d1,d2],新的函数的片段替代原来的部分,满足f'‘’>0,且新的函数的片段往d1外,点外延伸,比原来的数值小,满足f'(d1-delta)<f'(d1+delta),f'(d2-delta)<f'(d2+delta)

2.(-inf,d1],[d1,inf)同理。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define minv 1e-6
 5 #define inf 1e9
 6 #define pi 3.1415926536
 7 #define nl 2.7182818284
 8 const ll mod=1e9+7;//998244353
 9 const int maxn=1e5+10;
10 
11 int a[maxn],b[maxn],x[maxn],y[maxn],n;
12 double u[maxn],v[maxn],w[maxn];
13 
14 double f(double m)
15 {
16     double mm,z=0;
17     int i;
18     mm=m*m;
19     for (i=1;i<=n;i++)
20         z=max(z,u[i]*mm+v[i]*m+w[i]);
21     return z;
22 }
23 
24 int main()
25 {
26     int cond=0,i;
27     double l,r,m,mm,a,b;
28     scanf("%d",&n);
29     for (i=1;i<=n;i++)
30     {
31         scanf("%d%d",&x[i],&y[i]);
32         if (y[i]!=0)
33         {
34             if (cond==0)
35                 cond=(y[i]>0);
36             else if (cond!=(y[i]>0))
37             {
38                 printf("-1");
39                 return 0;
40             }
41         }
42         y[i]=abs(y[i]);
43         u[i]=0.5/y[i];
44         v[i]=-1.0*x[i]/y[i];
45         w[i]=(1.0*x[i]*x[i]+1.0*y[i]*y[i])/2/y[i];
46     }
47     l=-1.0e7,r=1.0e7;
48     while (1)
49     {
50         m=(l+r)/2;
51         mm=(m+r)/2;
52         a=f(m);
53         b=f(mm);
54         if (fabs(a-b)/max(1.0,min(a,b))<1e-8)
55             break;
56         if (f(mm)>f(m))
57             r=mm;
58         else
59             l=m;
60     }
61     printf("%.10f",a);
62     return 0;
63 }

 

 

类似:

hdu4717 The Moving Points

 

posted @ 2018-10-13 23:03  congmingyige  阅读(181)  评论(0编辑  收藏  举报