洛谷p1873:二分答案
思路:
首先明确符合得到木材至少为M米的答案有多种,当H最大,在升高H则不符合题意,而减小H会使得到木材进一步增多,从而知道,答案在一个单调区间内,显然答案在区间0-a.max,考虑二分答案
代码:
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll m,n,a[1000005];
ll i;
bool check(ll ans)
{
ll sum=0;
for(i=1;i<=n;i++)
{
if(a[i]>ans)sum+=(a[i]-ans);
else continue;
}
if(sum>=m)return 1;
else return 0;
}
int main ()
{
cin>>n>>m;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
ll l=1,r=a[n];
while(r-l>1)
{
ll mid=(l+(r-l)/2);
if(check(mid))l=mid;
else r=mid;
}
printf("%lld",l);
return 0;
}
美化一下:
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll m,n,a[1000005];
ll i;
bool check(ll ans)
{
ll sum=0;
for(i=1;i<=n;i++)
{
if(a[i]>ans)sum+=(a[i]-ans);
else continue;
}
if(sum>=m)return 1;
else return 0;
}
ll jdu(ll l, ll r)
{
if(r-l<=1)return l ;
ll mid=(l+(r-l)/2);
if(check(mid))jdu(mid,r);
else jdu(l,mid);
}
int main ()
{
cin>>n>>m;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
ll l=1,r=a[n];
printf("%lld",jdu(l,r));
return 0;
}
洛谷p2440:二分答案
思路:明确答案在一个固定区间内,即1到((sum/n)+1),计算发现当答案ans成立,ans-1也成立,但ans+1不成立,即答案左边合法右边非法,采用二分答案的做法
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k,l[100005],sum=0;
ll check(ll ans)//ans是当前l的值
{
ll total=0;
for(ll i=1;i<=n;i++)
{
total+=(l[i]/ans);//判断每根木材对于当前l的值能切成几段
if(total>=k)return 1;//大于k就直接return 1;
}
return 0;
}
int main ()
{
cin>>n>>k;
for(ll i=1;i<=n;i++)
{
cin>>l[i];
sum+=l[i];//统计木材总长度
}
if(sum<k)//连一厘米都切不出来
{
printf("0");
return 0;
}
ll ave=sum/n;
ll left=1,right=ave+1;//答案在该区间
while(right-left>1)
{
ll mid=(left+(right-left)/2);
if(check(mid))left=mid;
else right=mid;
}
printf("%lld",left);
return 0;
}