二分題目總結(未完待續)

2021-09-06 19:52:09 字數 4203 閱讀 3111

二分的用處太大了,不管是求簡單的方程,還是求最優解方面都是不錯的解題思想。

不過就像《程式設計珠璣》中說的一樣,雖然二分思路及其做法很爽,但是編寫二分的程式總是錯漏百出的。二分的第乙個程式出現在2023年,但是直到2023年出出現了第乙個沒有bug的二分程式,其編寫正確難度可想而知。

解題技巧:

(1)整形資料題目:l 為下界,r 為上界

一般的整形資料的題其迴圈都是 :

while ( l < r )   然後l=mid+1,high=mid 這各形式的;

或者有的題目邊界要求比較強就得是  

while ( l <= r) 然後 l=mid+1,r=mid-1 這各形式;

還有道題就是cf 371c那道中的邊界處理要求比較高就是:

while(  l+1 < r ) 然後 l=mid,r=mid

(2)浮點型題目: #define eps 1e-5

大神說的話:「一般浮點型題目都會與精度打交道,所以勢必與eps有關,因為如果如果精度要求0.01,那麼如果你在 l=mid+eps這樣做的話,這裡我設eps為0.00001,那麼時間複雜度就會乘以10^3了,那麼既然二分是減少時間的,這樣又會增加時間複雜 度,那該怎麼避免這個problem呢。

所以在hdu 1551這題上我就掉進了這個坑了,我把精度寫在 l=mid+eps裡了,然後直接tle。 我把精度寫在while裡面的時候時間直接下降很多。因為每次都是平分,這就與eps沒多大關係了,只要能接近最優答案就行。所以技巧如下:

while( r - l >eps)  然後 l=mid , r=mid;即可。」。

解題的基本思路就是:

while( l < r )

下面是這些題的**及分析:

hdu1551    cable master   

算是我的二分第一題吧,題意是給你n根繩子,讓你分成長度相等m段,求繩子的最長長度。以前根本不知道這種題可以用二分來做,感覺很神奇。

**如下:

#include #include 

#include

#include

#include

#define eps 1e-8

using

namespace

std;

intn,m;

double

sum;

double a[10001

];bool judge(double

s)

if(cnt>=m) return

true

;

else

return

false;}

intmain()

sum/=m;//繩子可以分的最大長度

double l=0,r=sum;

while(fabs(r-l)>eps)

printf(

"%.2lf\n

",l);

}return0;

}

hdu4109: distributing ballot boxes  

這題就是上面那題的變形。

有n個城市,m個投票箱。

然後是n行,表示每個城市的人口數。

現在每個城市所有的人要投票,投票箱的大小可以無限大(投票箱全部相同,大小相等),我們現在要求的是最小的投票箱容納量。

解題思路:

如果n == m,則容量肯定為城市人口數最多的那個。

如果n < m,我們當然要把m全部用光,因為用的箱子越多,平均值越小。這樣,我們就可以二分列舉人口數作為投票箱的容量,如果對於當前容量,我們列舉所有城市需要 的箱子數目,小於需要的箱子就說明還可以再小,如果需要的箱子數大於給出的箱子數,說明結果不符。

ps:

函式名: ceil

用 法: double ceil(double x);

功 能: 返回大於或者等於指定表示式的最小整數

標頭檔案:

math.h

說明:float ceil ( float value )

返回不小於 value 的下乙個整數,value 如果有小數部分則進一位。ceil() 返回的型別仍然是 float,因為 float 值的範圍通常比 integer 要大。

#include #include 

#include

#include

#include

#define eps 1e-9//

1e-5就wa了

using

namespace

std;

intn,m;

double

maxx,mid,sum;

double a[500001

];int judge(int

r) }

if(cnt>m)

return1;

}int

main()

if(n==m)

sum/=m;

double l=sum,r=maxx;

while(fabs(r-l)>eps)

else

}printf(

"%.0lf\n

",l);

}return0;

}

大神的**,寫的比我的好

#include#include

#include

#include

#include

#include

using

namespace

std;

int a[500010

];int

main()

if(city ==box)

l = 1, r =res;

while(l

if(flag) r = mid; //

中間值可以就減半

else l = mid + 1; //

不可以則mid+1

} printf(

"%d\n

", r);

}return0;

}

view code

poj3273: monthly expense 

題意:就是給出n個數,然後分成m組,要求分得各組的花費之和應該盡可能地小,最後輸出各組花費之和中的最大值。

感覺:二分可以求方程的解,這個我承認。不過這題確實有點神哦……這樣也能二分,太神了.

題意:二分列舉最佳的最大值,然後用最大值去列舉這n個數能分成的組數,逐漸逼近最優答案即可。

#include #include 

#include

#include

#define inf 0x3f3f3f3f

using

namespace

std;

int n,m,maxx,a[100005

];int

sum;

bool judge(int

r) }

if(cnt<=m)

return

true

;

return

false;}

intmain()

int l=maxx,r=sum;

while(l

else l=mid+1

; }

cout

}return0;

}

sdut2862:勾股定理(二分基礎題) 

校賽的題目,當時沒做出來,以後只要遇到查詢的題目首先就要考慮二分查詢,因為普通查詢時間複雜度o(n),而二分查詢是o(lgn)。

#include #include 

#include

#include

#include

using

namespace

std;

intn;

long

long a[1001

];bool er(long

long a,int lf,int rf,long

long

key)

else

}return

false;}

intmain()

sort(a,a+n);

for(int i=0; i<=n-3; i++)}}

cout

}return0;

}

設計模式總結(未完待續)

一 策略模式 可參看 應用場景 多種策略 演算法應用於同一用途 比如都是排序演算法 不同的情況需要用不同的策略 比如內部排序用快排,外部排序用歸併 由客戶端去決定具體呼叫哪乙個策略或演算法。一般的實現形式 每種策略類實現同乙個介面,實現演算法。由乙個context類通過構造方法引入具體的策略物件,封...

Linux學習總結 未完待續

linux學習總結 1.使用者管理部分 a,使用者與組配置檔案 a1.與使用者和組相關的配置檔案 passwd,shadow group,gshadow a2.超級許可權控制sudo的配置檔案 etc sudoers a3.新增使用者規則檔案 etc skel 預設啟動檔案 etc login.de...

未完待續 設計模式學習總結

一 設計模式的分類 1.1 根據目的分類 1 建立型 關注物件的建立過程,描述如何將物件的建立和使用分離,讓呼叫者無需關心物件的建立細節,降低耦合的同時也更易於修改和擴充套件 2 結構型 用於處理類或物件的組合,將現有類或物件組織在一起形成更加強大的結構,3 行為型 用於描述類或物件怎樣互動和怎樣分...