一、整数二分
int bs1(int l, int r) {
while(l < r) {
int mid = (l + r) >> 1;
//如果满足某种性质,答案在左半边
if(check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
int bs2(int l,int r){
while(l<r){
int mid = (l+r+1)>>1;
//如果满足某种性质,答案在右半边
if(check(mid)) l = mid;
else r = mid -1;
}
return l;
}
emm…来一道题记录一下,帮助自己理解
链接: 传送门.
既然是找到第一次出现的位置,答案严格在左半边,我们选择使用第一个模板,while(a[mid]<=x) r = mid; 一直往左找对吧
void solve() {
_read(n), _read(m);
_rep(i, 1, n) _read(a[i]);
while(m--) {
int x;
_read(x);
int l = 1, r = n;
while(l < r) {
int mid = (l + r) >> 1;
if(a[mid] >= x) r = mid;
else l = mid + 1;
}
//还得判断一下,万一超了边界
if(a[r] == x) cout <<r << " ";
else cout << "-1 ";
}
}
二、小数二分
double bs3(double l, double r) {
while(r - l > 精度) {
double mid = (l + r) >> 1;
if(check(mid)) r = mid;
else l = mid;
}
return l;
}
链接: 传送门.
int a, b, m;
int check(double mid) {
double s = a;
_rep(i, 1, m) {
s = s + s * mid - b;
}
if(s >= 0) return 1;
else return 0;
}
void solve() {
_read(a), _read(b), _read(m);
double l = 0, r = 500;
while(r - l > 1e-5) {
double mid = (l + r) / 2;
if(check(mid)) r = mid;
else l = mid;
}
printf("%.1f", l * 100);
}
三、lower_bound()和upper_bound()
lower_bound:返回迭代器,指向大于等于key的第一个值的位置
upper_bound:返回迭代器,指向大于key的第一个值的位置
数组中使用:
int a[]={1,2,3,4,5,7,8,9}; //一定要是有序数组
printf("%d",lower_bound(a,a+8,6)-a);
/*
output:
5
*/
vector中使用:
vector<int> a; //1 2 3 4 5 6 7 8 9
printf("%d",lower_bound(A.begin() , A.end() , 6)-A.begin());
/*
output:
5
*/
map中使用:
map<int,string>::iterator p1,p2;
p1 = mp.lower_bound(3);
p2 = mp.upper_bound(3);
cout<<"lower_bound"<<p1->first<<"=>"<<p1->second.c_str()<<endl;
cout<<"upper_bound"<<p2->first<<"=>"<<p2->second.c_str()<<endl;