關於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)是個上界,所以應該更新一個左閉右開區間。
所以,寫二分的時候,關鍵在於判斷問題到底是小於等於的符合條件還是大於等於的符合條件,然後選擇合適的半開半閉區間進行更新。更新的時候不滿足條件更新開區間那半邊,滿足條件的時候更新閉區間的哪一方,到最後肯定就是滿足條件與不滿足條件的分界線了。