关于2分,实在是自己的痛处,上次区域赛热身的时候把2分写挂了,被黑了好几个月了= =,幸亏我有强大的心脏。。
2分的用处不仅仅在于查找,还有很多用处,比如2分答案,查询满足条件的最大值,或者查询满足条件的最小值,又或者是平均值。
我写的2分是这个样子的(取自 线段树和树状数组各过一次POJ2182)
因为我要找的是满足空格数符合条件的最小的一个值,也就是找下界,所以选择更新一个左开右闭的值,确保我找到的是下界。PS:解释看下面
int bifind(int x)
{
int lb=0,ub=n;
while(ub-lb>1)
{
int mid=(ub+lb)>>1;
int s=sum(mid);
if(s>=x)
ub=mid;
else
lb=mid;
}
return ub;
}
但是写2分的时候最关键的是找到符合条件的那个答案和不符合条件的那个答案的那条分界线。这样才能决定你到底是写左开右闭区间的2分还是写右闭左开区间的2分。
当你2分的答案区间是 小于答案的都不符合 大于等于答案的都符合的时候,其实你是找的一个下界 ,因此你应该更新(lb,ub] 这样一个区间,这样保证了lb永远是个不符合条件的值,ub是符合条件的值,找到分界线就是ub-lb=1的时候,ub就是这样满足条件的一个最小值。
反之,当你2分的答案区间是这样的:大于答案的都不符合条件,小于等于答案的都符合条件的时候,你找的分界线应该是 [lb,ub)是个上界,所以应该更新一个左闭右开区间。
所以,写二分的时候,关键在于判断问题到底是小于等于的符合条件还是大于等于的符合条件,然后选择合适的半开半闭区间进行更新。更新的时候不满足条件更新开区间那半边,满足条件的时候更新闭区间的哪一方,到最后肯定就是满足条件与不满足条件的分界线了。