码迷,mamicode.com
首页 > 其他好文 > 详细

浅谈二分

时间:2018-10-02 20:25:58      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:设定   检查   判断   集合   相对   是的   范围   要求   math   

太极生两仪,两仪生四象,四象生八卦,阴阳交媾万物生。

若要你在全校同学当中猜我心里想的那个人,允许你问若干个问题,使问问题次数尽量少,你肯定会问我那个人是男生还是女生。因为这样,可以筛掉一半的人。并且在数学期望上来说,你肯定会尽量问一些能筛掉一半的问题,将问题的答案集合一分为二。假设你直接问是不是***,我说不是的话,你这个问题就问得十分无力了,因为它只帮你排除了一个人。所以,每次问可以筛掉一半备选集合的问题,显然是一种很聪明的做法。

世间万物始于混沌,根据太极生两仪,两仪生四象,四象生八卦,我们可以很快将万事万物分为八类,并且都相对均衡,这种古老的大智慧,在很久很久以前就被古人所运用了。

\(OI\)界,这就叫二分。一分为二,天地初开。

对于一个包含了最终解的集合,若我们能通过一次判断将其一分为二,将最终解的范围缩小一半,那么这就是二分。就比如,假如整数范围\([l,r]\)是解集范围,并且这个解具有单调性(不存在\(i\)是解但是\(j\)不是解且\(j>i\)),那么只要\(mid=(l+r)/2\)是解,\([mid+1,r]\)就都是解集,我们再去\([l,mid-1]\)里找更加小的解。因为满足单调性,二分多用于解决“最大值最小”或者“最小值最大”的问题。我要求某个问题的答案最大值最小的那一个,说明只要大于等于这个答案的都是问题的解,不过不是最小的。最小值最大同理。

至于二分的写法,网上千千万,我个人偏爱一下这一种:

int l=mn,r=mx,ans;
while(l<=r) {
    int mid=(l+r)>>1;
    if(check(mid))ans=mid,l=mid+1;
    else r=mid-1;
}//最小值最大
int l=mn,r=mx,ans;
while(l<=r) {
    int mid=(l+r)>>1;
    if(check(mid))ans=mid,r=mid-1;
    else l=mid+1;
}//最大值最小

因为\(mid\)已经被检查过并且用于更新\(ans\)了,所以剩下俩区间就是\([l,mid-1]\)\([mid+1,r]\)了,选择哪个继续去更新答案根据实际情况定就行。

然后实数二分的话只要设置一个\(eps\)判一判就行了:

double l=mn,r=mx,ans;
while(l+eps<=r) {
    double mid=(l+r)/2;
    if(check(mid))ans=mid,r=mid-eps;
    else l=mid+eps;
}

以上就是二分的板子了。至于怎么去二分和怎么去\(check\),那就得根据实际题目实际设定了。

浅谈二分

标签:设定   检查   判断   集合   相对   是的   范围   要求   math   

原文地址:https://www.cnblogs.com/AKMer/p/9737477.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!