二分3——二分答案
T1 母鸡下蛋(解法2)
题目:
题目二分2那里有,就不敲出来了,
要看题目的话……这里→ 二分2——2021-02-02更
思路:
解法1中我们用的是二分查找,这次用二分答案来做,每次都求一个x,再写一个函数用来判断x个鸡窝能否装完这些蛋,如果可以,则说明目前x个鸡窝满足条件,那就往小设置x,如果不可以,则将x往大设置。最后输出最小的x。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,a[1000010],h,t;
bool chk(int x)
{
for(int i=x;i<=n;i++)
if(a[i]-a[i-x]>=t)
return true;
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>t;
for(int i=1;i<=n;i++)
{
int k;
cin>>k;
a[i]=a[i-1]+k;
}
int z=1,y=n;
while(z<y)
{
int m=(z+y)/2;
if(chk(m))
y=m;
else
z=m+1;
}
if(chk(y))
cout<<y;
else
cout<<"Angry";
return 0;
}
T2 排队上车
题目:
现在有 n 个旅游团在排队等候观光车,每个旅游团有 ai 人,目前有 k 部巴士,各旅游团要安排在同一部车上,并且要按排队顺序依次上车。
请问如何分组,使得大巴中最多的人数最小?
例如:1 2 3 4 5 6 分为3组,可以分为 {1 2 3} {4 5} {6},最大值为9;也可以分为{1 2 3 4} {5} {6},最大值为10。因此第一种方案更优。并且第一种方案的最大值是所有方案中最小的。
输入
第1行:2个数 n, k,中间用空格分隔,n为旅游团的数量,k为巴士的数量。(2 <= k < n <= 50000)
第2行包含 n 个空格隔开的整数,表示每个旅游团的人数ai,(1 <= ai <= 10^9)
输出
一个整数,表示最小的最大值。
输入样例
6 3
1 2 3 4 5 6
输出样例
9
思路:
这道题目我一开始的时候是想着用for套for来做的,但看了一下数据,完全不可能,50000³,大概是五万亿左右,这么大数据的查找,我就想到要用二分来做,我们还是列举一个最大值x,然后每次用一个布尔型的函数来判断,如果符合条件,那么就往小的数接着做二分,如果不符合,就往大的数做二分。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,a[1000010],h,t,y,z=0;
bool chk(long long x)
{
long long s=0,k=1;
for(int i=1;i<=n;i++)
{
s+=a[i];
if(s>x)
{
k++;
s=a[i];
}
}
if(k<=t)
return true;
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>t;
for(int i=1;i<=n;i++)
{
cin>>a[i];
y+=a[i];
z=max(z,a[i]);
}
while(z<y)
{
long long m=(z+y)/2;
if(chk(m))
y=m;
else
z=m+1;
}
cout<<z;
return 0;
}
T3 篮球赛
题目:
A班有 n 名学生,在上体育课的时候按学号站成了一排,现在老师要分组进行篮球赛,分组的要求为:不能超过 k 组,每组的同学是按学号连续的。
![](/qrcode.jpg)
由于同一组内身高差太大的话容易引起内部矛盾,因此老师定义了一个不和谐度:各组的最高身高与最矮的身高的差值。很显然,这个不和谐度是越小越好,现在给出这 n 个学生的身高,请计算最小的不和谐度。
输入
第一行包括两个正整数 n,k。(1<=k<=n<=10^5)
第二行包括用空格隔开的 n 个正整数,第 i 个正整数 ai 表示学号为 i 的学生的身高。( 1<=ai<=10^9)
输出
包括一个整数,表示最小的不和谐度。
输入样例
8 3
5 7 2 3 8 5 9 4
输出样例
5
思路:
这道题的思路和T2类似,只不过一些细节要注意,其他的就没什么区别。
PS:在判断一段的不和谐度时,是要每循环一次就把最大值和最小值更新一次,而不是只求出一个最高(最低)身高和每个人来比较。
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,a[1000010],h,t,y,w;
bool chk(long long x)
{
long long s1=a[1],s2=a[1],k=1;
for(int i=2;i<=n;i++)
{
s1=max(a[i],s1);
s2=min(a[i],s2);
if(s1-s2>x)
{
k++;
s1=a[i];
s2=a[i];
}
}
if(k<=t)
return true;
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>t;
for(int i=1;i<=n;i++)
{
cin>>a[i];
y=max(y,a[i]);
w=min(w,a[i]);
}
if(n<=t)
{
cout<<0;
exit(1);
}
long long z=1;
y-=w;
while(z<y)
{
long long m=(z+y)/2;
if(chk(m))
y=m;
else
z=m+1;
}
cout<<y;
return 0;
}
今日心得:二分答案,就是用二分查找每次列举出一个值,然后判断是否符合要求,再做二分查找,一直做到结束为止。