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;
}

  

posted @ 2020-02-01 12:31  东坡肉肉君  阅读(984)  评论(0编辑  收藏  举报