- 整数二分模板
#整数二分
//1.满足某个条件的第一个数(右半段) //最大值最小
int fn(int l, int r){
while(l<r){
int mid=l+r>>1;
if(check(mid))r=mid;
else l=mid+1;
}
return l;
}
//2.满足某个条件的最后一个数(左半段) //最小值最大
int fn(int l,int r){
while(l<r){
int mid=l+r+1>>1;
if(check(mid))l=mid;
else r=mid-1;
}
return l;
}
·疑问与解答
1.当a[n]是从a[1]开始的时,l=0还是l=1,对应的r是n还是n+1;
2.While(l<r) / (l+1<r) / (l<=r) 有什么含义和用法上的不同吗
答:(1)当while(l<=r)时,l=mid-1;r=mid+1; 想求最小值就返回r,求最大值就返回l,想求中间的最佳值,就在if后加一个ans=mid次,存储最佳值
int fn(int l,int r){
while(l<=r){
int mid=l+r>>1;
if(check(mid))l=mid+1;
else r=mid-1;
}
return l;//最大值return l;最小值return r;
}
(2)当while(l<r)时,l == r ,不论l还是r都是答案,输出哪一个都可以
(3)当while(l+1<r)时,好问题,不晓得(待解答)
3.L+r+1>>1;什么情况下需要加这个防止死循环的1
答:仅第二种模板(最小值最大)
·附一道最小值最大的例题
P2678 [NOIP2015 提高组] 跳石头
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long cnt,n,m,a[50010],r,mid;
bool check(long long x){
int now=0,sum=0;
for(int i=1;i<=n;i++){//为什么用0循环会有样例不通过
if(a[i]-a[now]<x)sum++;
else now=i;
}
return sum<=m;
}
int main(){
cin>>r>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+n+1);
int l=0;
while(l<=r){
mid=l+r>>1;
if(check(mid)){
cnt=mid;
l=mid+1;
}
else r=mid-1;
}
cout<<cnt<<endl;
return 0;
}
·浮点数二分模板
#小数二分
//1.迭代100次
int fn(double l,double r){
for(int i=0;i<100;i++){
double mid=(l+r)/2;
if(check(mid))r=mid;
else l=mid;
}
return l;
}
//2.无边界问题
int fn(double l,double r){
double eps=1e7;//eps表示精度
while(r-l>eps){//要求保留或精确到第n位,则写n+2位,如精确到5位就写1e7;
if(check(mid))l=mid;
else r=mid;
}
return l;
}
·疑问与解答:
1.是只需要循环100次吗,有什么情况下循环次数会更改
答:不晓得(待解答)
· 附一道浮点数二分的例题
P3743 kotori的设备
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,p,a[100010],b[100010];
bool check(double x){
double sum=0;
for(int i=1;i<=n;i++){
if(b[i]<a[i]*x)sum+=x*a[i]-b[i];//所需要的电量
}
return sum<=x*p;//判断充电是否可以满足mid的时间
}
int main(){
cin>>n>>p;
double sum=0;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
sum+=a[i];
}
if(sum<=p){
cout<<-1;
return 0;
}
double l=0,r=1e10,mid;
while(r-l>=0.000001){//二分时间
mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
printf("%lf",l);
return 0;
}