2021-09-05算法周記——根號分治學習


本周小結

這周復習了平衡樹的內容,學習了根號分治的算法思想。
根號分治聽起來比較冷門,但是是一種很好用也很精妙的思想。

根號分治

一道題目:哈希沖突

暴力

如果使用暴力,每次詢問掃一遍,對於一次查詢的時間復雜度為\(O(\frac{n}{x})\)。當\(x=1\)時是最差時間復雜度,也就是說,最壞情況下,總體時間復雜度是\(O(mn)\)
但是,如果是隨機的呢?
我們知道調和級數\(\sum_{i=1}^{n}\frac{n}{i} \approx n\log n\),所以隨機數據的單點問詢時間復雜度為\(O(\log n)\)!在隨機數據下,暴力的時間復雜度不會很差!

從詢問入手

這也是我感到新奇的地方,這種思想的精妙之處也體現在這里。
我們發現:對於\(x\)較大的情況,即使是暴力去做也是很快的。主要就是思考對於\(x\)較小時如何去做。(\(x\)較大和較小的定義后文會說)
於是現在暴力處理小\(x\)時的缺陷需要彌補,其實對於較小的\(x\)而言,我們可以將當前序列拆成\(x\)個小序列。具體來說,是定義一個二維數組\(ans[i][j]\),表示當前模\(i\)\(j\)池子的元素總和。
所以,我們現在假設一個數\(L\)。當\(x\leq L\)時叫做\(x\)較小,當\(x>L\)是叫做\(x\)較大。對於較小的\(x\),需要定義數組int ans[SIZ][SIZ];。一開始的預處理是\(O(nL)\)的時間,每加入一個元素是\(O(L)\)的時間,查詢較小\(x\)的時間復雜度是\(O(1)\),較大\(x\)的時間復雜度是O(\frac{n}{L})$

時間復雜度分析

接下來分析\(L\)的取值,以及總體的時間復雜度
分析最壞情況下的時間復雜度,假設有\(uC\)個查詢,\(uA\)個加入總時間為\(O(nL+uA\times L+uC\times \frac{n}{L})\)
\(O(L(n+uA)+uC\times \frac{n}{L})\)
根據均值不等式,得出時間復雜度最小是\(L(n+uA)+uC\times \frac{n}{L}>=2\sqrt{(n+uA)*uC*n}\approx O(\sqrt{(n+uA)*uC*n})\)
根據均值不等式取最小值的條件,\(L(n+uA)=uC\times \frac{n}{L}\)
所以\(L=\sqrt{\frac{uC*n}{n+uA}}\)
如果覺得統計\(uC\)\(uA\)麻煩的話,可以近似的取\(uA=uC=\frac{m}{2}\)
最終,\(L=\sqrt{\frac{mn}{2n+m}}\),時間復雜度為\(O(\sqrt{n^2m+nm^2})\)

注意出錯的點

1、\(L\)求出來后最好與\(SIZ\)比較大小,避免ans數組越界
2、雖然是分塊,但\(L\)的取值並不是簡單的\(\sqrt n\)

其他題目

SHOI2006homework 一種很好的根號分治,\(L\)取值較為麻煩,可以將詢問一並讀入后直接取\(L=\sqrt{R}\)\(R\)為最大的數)

想法

根號分治就是將詢問分為兩部分,而時間復雜度是與這種詢問有關的。需要取得一個平衡,那么就要用兩種不同的方法來解決題目。一種是善於處理小數據的,一種是善於處理大數據的。如此可以使得時間復雜度成為平衡,時間復雜度的計算以及\(L\)值的選取是很重要的一個難點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM