『一本通』二分与三分

传送门:《信息学奥赛一本通》提高版题解索引


愤怒的牛

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,ans,a[100005];
 4 
 5 int check(int x) {
 6     int cnt=1,lst=a[1];
 7     for(int i=2;i<=n;i++)
 8      if(a[i]-lst>=x) cnt++,lst=a[i];
 9     return cnt;
10 }
11 
12 int main() {
13     scanf("%d%d",&n,&m);
14     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
15     sort(a+1,a+n+1);
16     int l=1,r=a[n]-a[1];
17     while(l<=r) {
18         int Mid=l+r>>1;
19         if(check(Mid)>=m) l=Mid+1,ans=Mid;
20         else r=Mid-1;
21     }
22     printf("%d",ans);
23 }

Best Cow Fences

 1 #include<bits/stdc++.h>
 2 #define N 100005
 3 using namespace std;
 4 int n,L,ans,a[N];
 5 long long s[N];
 6 
 7 bool check(int x) {
 8     for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i]-x;
 9     long long Min=0;
10     for(int i=L;i<=n;i++) {
11         Min=min(Min,s[i-L]);
12         if(s[i]>=Min) return 1;
13     }
14     return 0;
15 }
16 
17 int main() {
18     scanf("%d%d",&n,&L);
19     int l=0,r=0;
20     for(int i=1;i<=n;i++) {
21         scanf("%d",&a[i]);
22         a[i]*=1000,r=max(r,a[i]);
23     } 
24     while(l<=r) {
25         int Mid=l+r>>1;
26         if(check(Mid)) l=Mid+1,ans=Mid;
27         else r=Mid-1;
28     }
29     printf("%d",ans);
30 }
31 /*
32 二分枚举平均值ave。
33 将每个数减去ave,看是否有长度不小于L的连续区间,使得这段区间的和大于等于0。
34 */

数列分段II

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,a[100005];
 4 
 5 bool check(int x) {
 6     int cnt=1,sum=a[1];
 7     for(int i=2;i<=n;i++) {
 8         sum+=a[i];
 9         if(sum>x) cnt++,sum=a[i];
10         if(cnt>m) return 0;
11     } return 1;
12 }
13 
14 int main() {
15     scanf("%d%d",&n,&m);
16     int l=0,r=0;
17     for(int i=1;i<=n;i++) {
18         scanf("%d",&a[i]);
19         l=max(l,a[i]),r+=a[i];
20     }
21     while(l<=r) {
22         int Mid=l+r>>1;
23         if(check(Mid)) r=Mid-1; 
24         else l=Mid+1;
25     }
26     printf("%d",l);
27 }
28 //二分答案

曲线

 1 #include<bits/stdc++.h>
 2 #define eps 1e-10
 3 using namespace std;
 4 int T,n;
 5 struct node{double a,b,c;}s[100005];
 6 
 7 double F(double x) {
 8     double f=-1e10;
 9     for(int i=1;i<=n;i++)
10      f=max(f,s[i].a*x*x+s[i].b*x+s[i].c);
11     return f;
12 }
13 
14 int main() {
15     T=read();
16     while(T--) {
17         n=read();
18         for(int i=1;i<=n;i++)
19          s[i]=(node){read(),read(),read()};
20         double l=0,r=1000;
21         while(l+eps<=r) {
22             double Mid=(l+r)/2;
23             if(F(Mid)>=F(Mid+eps)) l=Mid;
24             else r=Mid;
25         }
26         printf("%.4lf
",F(l));
27     }
28 }
29 //二分枚举x

 扩散

 1 #include<bits/stdc++.h>
 2 #define N 55
 3 using namespace std;
 4 int T,n,ans,x[N],y[N],fa[N];
 5 int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
 6 
 7 bool check(int t) {
 8     for(int i=1;i<=n;i++) fa[i]=i;
 9     for(int i=1;i<n;i++)
10      for(int j=i+1;j<=n;j++) {
11         int d=abs(x[i]-x[j])+abs(y[i]-y[j]); //曼哈顿距离
12         if(d<=2*t) { //不超过时间的2倍(两个点都能扩散) 
13             int fi=find(i),fj=find(j);
14             if(fi!=fj) fa[fi]=fj;
15         }
16      }
17     int tot=0;
18     for(int i=1;i<=n;i++) if(fa[i]==i) tot++;
19     if(tot==1) return 1; //如果只有一个联通块 
20     return 0;
21 }
22 
23 int main() {
24     scanf("%d",&n);
25     for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
26     int l=0,r=1e9;
27     while(l<=r) { //二分答案 
28         int Mid=l+r>>1;
29         if(check(Mid)) r=Mid-1,ans=Mid;
30         else l=Mid+1;
31     }
32     printf("%d",ans);
33 }

灯泡

 

 1 #include<bits/stdc++.h>
 2 #define eps 1e-8 
 3 using namespace std;
 4 int T;
 5 double D,H,h;
 6 double F(double x) {return D-x+H-(H-h)*D/x;} 
 7 
 8 int main() {
 9     scanf("%d",&T);
10     while(T--){
11         scanf("%lf%lf%lf",&H,&h,&D);
12         double l=D*(H-h)/H,r=D; //或 l=D-D*h/H
13         while(r-l>eps) {
14             double M1=(l+r)/2.0;
15             double M2=(M1+r)/2.0;
16             if(F(M1)<F(M2)) l=M1; else r=M2;
17         }
18         printf("%.3lf
",F(l));
19     }
20 }

传送带

 1 #include<bits/stdc++.h>
 2 #define eps 1e-6
 3 using namespace std;
 4 int P,Q,R;
 5 struct node{double x,y;}A,B,C,D,a,b;
 6 double dis(node a,node b) {
 7     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 8 }
 9 
10 double cal(double p1,double p2) {
11     a.x=A.x+(B.x-A.x)*p1;
12     a.y=A.y+(B.y-A.y)*p1;
13     b.x=C.x+(D.x-C.x)*p2;
14     b.y=C.y+(D.y-C.y)*p2;
15     return dis(A,a)/P+dis(a,b)/R+dis(b,D)/Q;
16 }
17 
18 double get(double x) {
19     double l=0,r=1;
20     while(r-l>eps) {
21         double M1=l+(r-l)/3.0,M2=r-(r-l)/3.0;
22         if(cal(x,M1)>cal(x,M2)) l=M1; else r=M2;
23     }
24     return cal(x,l);
25 }
26 
27 int main() {
28     cin>>A.x>>A.y>>B.x>>B.y;
29     cin>>C.x>>C.y>>D.x>>D.y;
30     cin>>P>>Q>>R;
31     double l=0,r=1;
32     while(r-l>eps) {
33         double M1=l+(r-l)/3.0,M2=r-(r-l)/3.0;
34         if(get(M1)>get(M2)) l=M1; else r=M2;
35     }
36     printf("%.2lf",get(l));
37 }
38 //三分(a点)套三分(b点) 

完结 (2019.1.29)

原文地址:https://www.cnblogs.com/qq8260573/p/10331491.html