二分小结

二分这玩意,整数型的总是会搞错额。。

今天终于算是搞懂了,在题目中再多磨练磨练把。

推荐博客:http://www.cppblog.com/converse/archive/2009/09/21/96893.html

个人倾向于写法是:

while(l<r),所以我的这种写法是属于左闭右开区间的那种类型。

那么if(a[mid]>v)时,我应该写成r=mid,因为右边是开的,如果写成r=mid-1,则会遗漏a[mid-1]的情况。

else时,应该写成l=mid+1,因为左边是闭的,而且当前条件不成立,所以直接往右移就好。

昨天那道poj1505:

要求的是值尽量小,所以ans初始化为inf,

然后:

ll bin(ll x,ll y){
	ll ans=inf;
	while(x<y){
		ll mid=x+(y-x)/2;
		if(is_ok(mid)){
			y=mid;
			ans=min(ans,mid);
		}
		else x=mid+1;
	}
	return ans;
}

因为我们要求的是mid,所以只需要更新ans就好了。


昨天那道cf299div1的A题,则要求的是尽量大的值。

然后:

ll bin(ll x,ll y){
    ll mid;
    ll ans=-1;
    while(x<y){
        mid=x+(y-x)/2;
        if(is_ok(mid)){
        	x=mid+1;
        	ans=max(ans,mid);	//二分的时候可以用一个变量来保存结果! 
		}
        else y=mid;
    }
    return ans;
}
这里x+1的原因是因为当前x已经满足了,而且我们用了一个ans保存下来了中间结果mid,所以x可以往后去推了,所以x+1。

而上面那个x+1的原因是因为当前x不满足了,所以答案肯定在后面,所以x+1。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值