整数二分~

二分查找1

题目描述

给定一个n,再给定n个数,从小到大排列,给定一个x,说出小于等于x的最大的数。

输入描述

输入两行,第一行两个数分别是n,x。(1 <= n <= 1000000)

第二行有n个数。

输出描述

输出一个数,即答案。

#include<iostream>
#include<iomanip>
#include<cmath> 
#include<string>
#include<algorithm> 
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>
using namespace std;
int main(){
	 int n,x;
	int a[1000005];
	cin>>n>>x;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	int l=1,r=n;
	while(l<r){
		int mid=(l+r+1)>>1;
		if(a[mid]>x){
			r=mid-1;
		}
		else if(a[mid]<=x){
			l=mid;
		} 
	}

	cout<<a[l];
      return 0;
}

二分查找2

题目描述

给定一个n,再给定n个数,从小到大排列,给定一个x,说出大于等于x的最小的数。

输入描述

输入两行,第一行两个数分别是n,x。

(1 <= n <= 1000000)

第二行有n个数。

输出描述

输出一个数,即答案。

#include<iostream>
#include<iomanip>
#include<cmath> 
#include<string>
#include<algorithm> 
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>	
using namespace std;
int a[1000005];
int main(){
	 int n,x;
	cin>>n>>x;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	int l=1,r=n;
	while(l<r){
		int mid=(l+r)>>1;
		if(a[mid]>= x){
			r=mid;
		}
		else if(a[mid]<x){
			l=mid+1;
		} 
	}

	cout<<a[l];
      return 0;
}

砍伐树木

题目描述

小华被小林叫去砍树,他需要砍倒m米长的木材。现在,小华弄到了一个奇怪的伐木机。伐木机工作过程如下:小华设置一个高度参数h(米),伐木机升起一个巨大的锯片到高度h,并锯掉所有的树比h高的部分(当然,树木不高于h米的部分保持不变)。小华就得到树木被锯下的部分。 

例如,如果一行树的高度分别为20、15、10、17米,小华把锯片升到15米的高度,切割后树木剩下的高度将是15、15、10、15米,而小华将从第一棵树得到5米,从第4棵树得到2米,共得到7米木材 

小华非常关注生态保护,所以他不会砍掉过多的木材。这正是他为什么要尽可能高的设定伐木机锯片的原因。帮助小华找到伐木机锯片的最大的整数高度h,使得他能得到的木材至少为m米。换句话说,如果再升高1米,则他将得不到m米木材

输入描述

第一行两个整数n和m,n表示树木的数量,m表示需要的木材总长度 

第二行n个整数,表示每棵树的高度,值均不超过10^9.保证所有木材长度之和大于m,因此必然有解

输出描述

一行一个整数,表示砍树的最高高度

#include<iostream>
#include<iomanip>
#include<cmath> 
#include<string>
#include<algorithm> 
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>	
using namespace std;
long long n,m,maxx;
long long a[1000005];
long long ck(long long mid){
long long sum=0;
    for(int i=1;i<=n;i++){
        if(a[i]>=mid){
            sum+=a[i]-mid;
        }
    }
    return sum;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        maxx=max(maxx,a[i]);
    }
    long long l=0,r=maxx;
    while (l<r){
        long long mid=(l+r+1)>>1;
        if(ck(mid)>=m){
			l=mid;
		} 
        else{
        	r=mid-1;
		}
    }
    cout<<l;
	return 0; 
}

月度开销

题目描述

农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。

他计算出并记录下了接下来 N (1 ≤ N ≤ 100,000) 天里每天需要的开销。 

约翰打算为连续的M (1 ≤ M ≤ N) 个财政周期创建预算案,他把一个财政周期命名为fajo月。

每个fajo月包含一天或连续的多天,每天被恰好包含在一个fajo月里。 

约翰的目标是合理安排每个fajo月包含的天数,使得开销最多的fajo月的开销尽可能少。

输入描述

第一行包含两个整数N,M,用单个空格隔开。

接下来N行,每行包含一个1到10000之间的整数,按顺序给出接下来N天里每天的开销。

输出描述

一个整数,即最大月度开销的最小值。

#include<iostream>
#include<iomanip>
#include<cmath> 
#include<string>
#include<algorithm> 
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>	
using namespace std;
int n,m,a[100005],maxx,sum=0;
int ck(long long mid){
	int cnt=1;
	int pos=mid;
	for(int i=1;i<=n;i++){
		if(mid>=a[i]){
			mid=mid-a[i];
		}
		else{
			cnt++;
			mid=pos;
			mid=mid-a[i];
		}
	}
	return cnt;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
	   cin>>a[i];
	   maxx=max(maxx,a[i]);
	   sum+=a[i];
	}
	long long l=maxx,r=sum;
	while(l<r){
		long long mid=(l+r)>>1;
		if(ck(mid)>m){
			l=mid+1; 
		}
		else{
			r=mid;
		}
	}
	cout<<l;
	return 0; 
}

 好斗的奶牛

题目描述

农夫约翰搭了一间有N个牛舍的小屋,牛舍排在一条线上,第i号牛舍在xi的位置。但是有M头牛对小屋很不满意。因此经常互相攻击。约翰为了防止牛之间相互伤害,因此决定把每头牛都放在离其他牛舍尽可能远的牛舍。

输入描述

第一行输入n(n<=1000)和m(m<=n)

接下来的n行有N个数,第i行为对应的xi

输出描述

输出距离最近的两头奶牛间的距离的最大值。 

#include<iostream>
#include<iomanip>
#include<cmath> 
#include<string>
#include<algorithm> 
#include<cstdio>
#include<queue>
#include<map>
#include<vector>
#include<stack>	
using namespace std;
int a[1000005]; 
int n,m;
int c(int mid){
	int cnt=1,pos=a[1];
	for(int i=2;i<=n;i++){
		if(a[i]-pos>=mid){
			cnt++;
			pos=a[i];
		}
	} 
	return cnt;
}
int main(){
	
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+1+n); 
	int l=1,r=a[n]-a[1];
	while(l<r){
		int mid=(l+r+1)>>1;
		if(c(mid)>= m){
			l=mid;
		}
		else if(c(mid)<m){
			r=mid-1;
		} 
	}
 
	cout<<l;
      return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值