noi寒假刷题之旅_ 1.11编程基础之二分查找(10题)
»1.11编程基础之二分查找(10题)
01:查找最接近的元素
#include<iostream> #include<algorithm> #include<cmath> #define MAX 100004 using namespace std; int t[MAX]; int main() { int n;cin>>n; for(int i=0;i<n;++i)cin>>t[i]; int m,a,low=0,high=n-1,f;cin>>m; for(int i=0;i<m;++i) { cin>>a; low=0,high=n-1,f=1; if(a<=t[low]){ cout<<t[low]<<endl;continue; } if(a>=t[high]){ cout<<t[high]<<endl;continue; } while(low<=high) { int mid=(low+high)/2; if(t[mid]<a) low=mid+1; else high=mid-1; } f = (abs(t[low]-a) < abs(t[high]-a)) ? low : high; cout<<t[f]<<endl; } return 0; }
02:二分法求函数的零点
#include<iostream> #include<algorithm> #include<cmath> #define MAX 100004 using namespace std; double t[6][2]={{1,5},{-15,4},{85,3},{-225,2},{274,1},{-121,0}}; double f(double x) { return pow(x,5)-15.0*pow(x,4)+85.0*pow(x,3)-225.0*pow(x,2)+274.0*x-121.0; } int main() { double low=1.5,high=2.4, mid; while(fabs(low-high)>1e-15) { mid=(low+high)/2.0; double re=f(mid); if(re>0) low=mid; else high=mid; } printf("%.6lf",mid); return 0; }
03:矩形分割
【降维,终于知错了if(Check(kk))与if(Check(kk)>0)是不一样的,一个是非0一个是大于0】
#include<iostream> #include<algorithm> #include<cmath> #define MAX 1000005 using namespace std; int a[MAX]; int r,n,k,L,T, W, H; long long Check(int k) { long long c=0,b=0; for(int i=0;i<k;++i) c+=a[i]; for(int i=k;i<r;++i) b+=a[i]; return c-b; } int main() { scanf("%d%d",&r,&n); for(int i=0;i<n;++i) { scanf("%d%d%d%d",&L,&T,&W,&H); for(int i=L;i<L+W;++i) a[i]+=H; } int low=0,high=r; while(low+3<high) { int kk=(low+high)/2; if(Check(kk)>0) high=kk; else low=kk; } long long su=0x3f3f3f3f; for(int i=high;i>=low;--i) { long long m=Check(i); if(m<su&&m>=0) { su=m;k=i; } } while(a[k]==0&&k<r)k++; printf("%d",k); return 0; }
04:网线主管
【可烦死这种求精度的了,long long的精度比int高,自己用整形取上整提精度】
#include<iostream> #include<algorithm> #include<cmath> #define MAX 1000005 using namespace std; double x; long long a[MAX],t,sum,z,mid; int n,k; int main() { scanf("%d%d",&n,&k); for(int i=0;i<n;++i) { scanf("%lf",&x); a[i]=int(x*100.00+0.5);//提炼一下精度 z = z > a[i] ? z : a[i]; sum+=a[i]; } int low = z/k;//最小长度 int high= sum/k;//最大长度 while(low<high) { mid=(low+high+1)/2,t=0; for(int i=0;i<n;++i) t+=int(a[i]/mid); if(t>=k)low=mid; else high=mid-1; } printf("%.2lf",low/100.00); }
05:派
#include<iostream> #include<algorithm> #include<cmath> #define MAX 1000005 using namespace std; double x; double a[MAX],sum,z,mid; int n,k,t;//保存每一个派的体积 double f(double r) { return r*r*3.1415926535897932; } int main() { scanf("%d%d",&n,&k);k++; for(int i=0;i<n;++i) { scanf("%lf",&x); a[i]=f(x); z = z > a[i] ? z : a[i]; //找体积最大的 } double low = 0,high=z; while(low<=high) { mid=(low+high)/2,t=0; for(int i=0;i<n;++i) t+=int(a[i]/mid); if(t>=k)low=mid+0.000001; else high=mid-0.000001; } printf("%.3lf",mid); }
06:月度开销
#include<iostream> #include<algorithm> #include<cmath> #define MAX 1000005 using namespace std; int a[MAX],t,mid; int n,m,low = 0,high=0; int f(int mid) { int count=1,i,temp=0; for(i=0;i<n;i++) { if(temp+a[i]<=mid) temp+=a[i]; else if(a[i]<=mid) { count++; temp=a[i]; if(count>m) return -1; } else return -1; } if(count>m) return -1; else if(count<=m) return 1; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;++i) { scanf("%d",&a[i]); low = low > a[i] ? low : a[i]; high+=a[i]; } while(low<high) { mid=(low+high)/2,t=f(mid); if(t==-1)low=mid+1; else high=mid; // cout<<low<<"_"<<mid<<"_"<<high<<endl; } printf("%d",low); }
07:和为给定数
#include<iostream> #include<algorithm> #include<cmath> #define MAX 1000005 using namespace std; int a[MAX],t,mid,flag=1; int n,m,low = 0,high=0; int main() { scanf("%d",&n); for(int i=0;i<n;++i)scanf("%d",&a[i]); scanf("%d",&m); sort(a,a+n); for(int i=0;i<n;++i)//小值 { low=i+1,high=n-1; while(low<=high)//大值 { mid=(low+high)>>1; if(a[mid]+a[i]<m){ low=mid+1; } else if(a[mid]+a[i]>m) { high=mid-1; } else { printf("%d %d",a[i],a[mid]);flag=0;goto stop; } } } stop:if(flag) { cout<<"No"; }return 0; }
08:不重复地输出数
【不知道二分在哪里】
#include<iostream> #include<algorithm> #include<cmath> #define MAX 1000005 using namespace std; int a[MAX],t,mid,flag=1; int n,m,low = 0,high=0; int main() { scanf("%d",&n); for(int i=0;i<n;++i)scanf("%d",&a[i]); sort(a,a+n); for(int i=0;i<n;++i)//小值 { if(a[i]!=a[i+1]) cout<<a[i]<<" "; } return 0; }
09:膨胀的木棍
【数学公式能化简化简,把三角函数的都化到最简单,不然精度上不去】
#include<iostream> #include<algorithm> #include<cmath> #define MAX 1000005 using namespace std; double L,n,C,low=0,high,mid; int main() { scanf("%lf%lf%lf",&L,&n,&C); if(L<1e-14) { printf("0.000"); return 0; } double LL=(1+n*C)*L; high=asin(1.0);//90° while(high-low>1e-14) { mid = (low+high)/2; if( LL * sin(mid)/mid <= L ) high=mid; else low=mid; } printf("%.3lf",L/2*tan(mid/2)); return 0; }
10:河中跳房子
#include<iostream> #include<algorithm> #include<cmath> #define MAX 50010 using namespace std; int L,N,M,s[MAX]; bool f(int mid) { int bp=0,leaf=0; for(int sp=1;sp<=N+1;++sp) { if(s[sp]-s[bp]>=mid){ leaf++;bp=sp; } } if(leaf>N-M)return true; else return false; } int main() { scanf("%d%d%d",&L,&N,&M); for(int i=1;i<=N;++i)scanf("%d",&s[i]);s[N+1]=L; int low=1,heigh=L,ans=0; while(low<=heigh) { int mid=(low+heigh)/2; if(f(mid)) { ans=mid;low=mid+1; } else { heigh=mid-1; } } printf("%d",ans); return 0; }