根號算法 I

Sqrt Decomposition & Techniques I

Gino

\[ \sqrt{     }\]

Warning

這份簡報已經停止施工

並移到 HackMD 上

https://hackmd.io/@penguin71630/sqrt1#/

內容大綱

★☆☆☆☆ 折半枚舉

★★☆☆☆ 序列分塊

★★☆☆☆ 塊狀鍊表

★★★☆☆ 值域分塊

★★★☆☆ 數論分塊

★★★★★ 根號分 case

★★★★★ 操作分塊
★★★★☆ 樹分塊
★★☆☆☆ 基礎莫隊算法
★★★★☆ 樹上莫隊
★★★★★ 回滾莫隊
★★★★★ 帶修改莫隊

根號算法 I

根號算法 II

折半枚舉

Meet In The Middle

例題

有 \(N\) 個正整數 \( a_1, a_2, ..., a_N\)

給定 \( x \),請問有多少子集

滿足子集和等於 \(x\)

 

  • 子題一:\(N \leq 20 \)
  • 子題二:\(N \leq 40 \)

子題一很簡單

\(O(2^N)\) 暴力枚舉 + \(O(N)\) 檢查

複雜度 \(O(N \cdot 2^N) \)

子題一很簡單

\(O(2^N)\) 暴力枚舉 + \(O(N)\) 檢查

複雜度 \(O(N \cdot 2^N) \)

 

子題二?

把 \(N\) 個數字對半拆成兩組:A 組跟 B 組

A

B

\(a_1 \sim a_{\frac{N}{2}}\)

\(a_{\frac{N}{2}+1} \sim a_{N}\)

1. 暴力枚舉 A 的所有子集

對每個子集算出他的和

把這些和儲存在一個 set 裡面

A

B

\(a_1 \sim a_{\frac{N}{2}}\)

\(a_{\frac{N}{2}+1} \sim a_{N}\)

2. 暴力枚舉 B 的所有子集

對每個子集算出他的和

接著搜尋剛剛的 set 有多少數字跟它互補(相加為 \(x\))

A

B

\(a_1 \sim a_{\frac{N}{2}}\)

\(a_{\frac{N}{2}+1} \sim a_{N}\)

1. 暴力枚舉 A 的所有子集

對每個子集算出他的和

把這些和儲存在一個 set 裡面

A

B

\(a_1 \sim a_{\frac{N}{2}}\)

\(a_{\frac{N}{2}+1} \sim a_{N}\)

時間複雜度

\(O(2^{N/2} (N + \text{set 操作複雜度}))\)

2. 暴力枚舉 B 的所有子集

對每個子集算出他的和

接著搜尋剛剛的 set 有多少數字跟它互補(相加為 \(x\))

A

B

\(a_1 \sim a_{\frac{N}{2}}\)

\(a_{\frac{N}{2}+1} \sim a_{N}\)

時間複雜度

\(O(2^{N/2} (N + \text{set 操作複雜度}))\)

總時間複雜度

\(O(2^{N/2} (N + \text{set 操作複雜度}))\)

會把折半枚舉放在根號是因為 \(2^{N/2}\) 剛好是 \(2^N\) 開根號

因為可能有多個子集和是重複的

所以可以用 map<int, int> 紀錄和還有對應的出現次數

 

時間複雜度:\(O(2^{N/2} \cdot (N + \log 2^{N/2}) \in O(N \cdot 2^N)\)

實作細節

\(\Uparrow\) 用對數律把\(N/2\) 拿下來

算每個子集的和可以用 DP 的方式

\(sum[mask] = sum[mask \oplus anybit] + a[anybit]\)

\(anybit =\) 任意取一個值為 true 的位元

常數優化 I

位元的可以取最高的位元

可以用 __lg(mask) 得到每個 mask 的最高位元 index

所以可以這樣寫:

常數優化 I

如果用 __lg(mask) 被卡常的話

可以開大小 \(2^{N/2}\) 的陣列預處理每個 mask 的最高位元

位元也可以取最低的位元

有寫過 BIT 的話就會知道 \(x\) 的 lowbit 是 \(x \ \& \ (-x)\)

常數優化 I

map 改用 vector

枚舉完其中一邊的子集後對 vector sort

接下來要查詢數量可以用 upper_bound 跟 lower_bound

常數優化 II

枚舉 A 跟 B 的子集,把這些和存成兩個 vector

把這兩個 vector 都 sort

接著用雙指針算答案

常數優化 III

要算出所有子集和可以不要用 0/1 枚舉

改用倍增的方式

接著搭配優化 III

想了解的話可以參考 code

常數優化 IV

根號算法 I

By Gino

根號算法 I

附中 x 延平競程讀書會簡報

  • 88