整数二分模板:数的范围
二分的本质不是单调性,而是二分出能满足某种性质使得将整数分成两半。
思考:模板题,模板记熟就能做
#include<iostream>
using namespace std;
int n,q;
const int N = 1e5+10;
int a[N];
int main( ){cin>>n>>q;for(int i=0;i<n;i++)cin>>a[i];while(q--){int k;cin>>k;int l = 0,r = n-1;while(l<r){int mid = (l+r)>>1;if(a[mid]>=k)r=mid;else l=mid+1;}if(a[r]==k)cout<<r<<" ";else cout<<-1<<" ";l = 0,r = n-1;while(l<r){int mid = (l+r+1)>>1;if(a[mid]<=k)l=mid;else r=mid-1;}if(a[l]==k)cout<<l<<'\n';else cout<<-1<<'\n';}return 0;
}
冶炼金属
c++除法是下取整的
根据评测用例,可以看出需要设计 nlogn 的算法,也就是要用到二分。关键是二分时需要找到大于等于某值的上限和下限,边界条件确定比较细节和关键。思路:每次输入 A 和 B,通过二分来找到满足条件的V的上界和下界,min_v 为所有下界的最大值,max_v 相反。
#include<bits/stdc++.h>
using namespace std;
const int inf =0x3f3f3f3f;
int n;
int Min_v = 0,Max_v=inf;
int main( ){cin>>n;while(n--){int a,b;cin>>a>>b;int l = 0,r = a+1;while(l<r){int mid = (l+r)>>1;if(a/mid<=b)r=mid;else l=mid+1;}Min_v = max(Min_v,r);l = 0,r = a+1;while(l<r){int mid = (l+r+1)>>1;if(a/mid>=b)l=mid;else r=mid-1;}Max_v = min(Max_v,l);}cout<<Min_v<<' '<<Max_v<<'\n';return 0;
}
浮点二分:数的三次方根
思路:浮点二分不用模板直接做,细节是保留 6 位小数 while 要到 1e-8,保留 4 位 while 要到 1e-6,多两位,printf lf 默认保留 6位小数。
#include<iostream>
using namespace std;double n;int main( ){cin>>n;double l = -10000,r = 10000;while(r-l>=1e-8){double mid = (l+r)/2;if(mid*mid*mid<=n)l = mid;else r = mid;}printf("%.6f",r);return 0;
}