嗨嗨嗨,第一次写博客。
就写个上周学习的二分总结吧。
一.首先是两个二分万能模板(真的很万能!!!)
int a[n];
//模板1
int l=0,r=n-1;
while(r>l){
int mid=(l+r)/2;//对比第二个模板,+1不+1取决于满足check时是r更新还是l更新
if(check(mid)) r=mid;//根据check更新边界,check函数怎么写是关键(一般是分析题目,观察是否满足某种性质)
else l=mid+1;
//模板2
int l=0,r=n-1;
while(l<r){
int mid=(l+r+1)/2;
if(check(mid))l=mid;
else r=mid-1;
}
二.模板有了,关键是怎么用呢?
什么时候用呢?
1.找满足某种性质的特殊点的时候
2与数组相关联
(做题有限,嘿嘿,以后会补充...)
三.为什么用呢
1.降低时间复杂度,二分时间复杂度只有o(logn),1e5的数据不会超时。
2.提供思路,感觉二分还是挺好用的挺无脑的,(对我来说)难点在于check函数咋写。
四.整体大体写法以及check函数写法(难点)
一般是要在主函数里排序sort(数据要在1e5哦),把mid的值交到check里,一般check函数肯定会用到其他算法(二分+其他算法)。(个人理解)其实就是在主函数里不停“枚举”mid,不断缩小范围,然后在check函数里其实就是把每一个mid当成正确答案(特殊点),然后check他是不是满足性质,满足的话,那就说明选对了。通常在check函数中要计数,以便判断,并缩小正确的那个点的范围;
五.什么是二分
(这个应该放在第一条,写着写着突然想起来,就这样,不管啦)
说白了就是选一组数下标的中点mid,定义一种性质,判断满足不满足,来确定答案在mid的右边还是左边,不断更新左右边界。
六.常用函数
#include<iostream>
#include<algorithm>//在此文件中
using namespace std;
int main(){
int a[n];
int y=lower_bound(a,a+n,x)-a;//第一个位置是数组首地址,第二个位置是末位置+1,函数作用就是在a[0]到a[n-1]里找到第一个大于等于x的数(一定不要忘了-a),y等于的是值,不是下标!!!
upper_bound(a,a+n,x)-a;//找到第一个大于x的数
}