淺談莫隊分塊大小


淺談莫隊算法分塊大小

前言

  • 莫隊算法是一種非常經典優雅的暴力算法
  • 而在莫隊算法中,最值得探討的問題自然而然就是:這個塊的大小到底應該怎么分?
  • 有很多 \(OIer\) 將它看成一個玄學問題,非常有道理,但其實我們是能夠找到規律的。

普通莫隊

  • 普通莫隊最佳分塊大小為 \(\sqrt n\)
  • 為什么?因為暴力分塊的大小為 \(\sqrt n\) ?並不是。
  • 那為什么?
  • 我們不妨設塊的大小為 \(s\) ,每個塊的詢問次數為 \(q_i\) ,序列長度為 \(n\) ,詢問總次數為 \(m\) 。那么塊的總數就是 \(\frac{n}{s}\) ,對於塊 \(i\) 來說,其復雜度為 \(q_i\cdot s+n\)
  • 那么總復雜度為 \(\sum_{i=1}^{n/s} q_i\cdot s+n=ms+n\cdot \frac{n}{s}\) 。因為一般 \(n\)\(m\) 都是等數量級的,我們可以大致忽略其大小差異,所以總復雜度變為 \(n\cdot s+n^2\cdot \frac{1}{s}\)
  • 利用基本不等式可得當 \(n\cdot s=n^2\cdot \frac{1}{s}\)\(s=\sqrt n\) 時,原式有最小值 \(n\sqrt n\)
  • 這就是普通莫隊算法分塊的大小以及時間復雜度的來歷。

帶修莫隊

  • 帶修莫隊最佳分塊大小為 \(n^{\frac{2}{3}}\)可惜我不會證明
  • 所以我就僅僅裝模作樣地分析一番。
  • 一開始自學帶修莫隊的時候有一個疑問,為什么要將右端點也分塊?

  • 假如右端點不分塊,仍然設塊的大小為 \(s\) ,序列長度為 \(n\) ,詢問總次數為 \(m\) ,修改總次數為 \(k\) 。那么塊的總數還是 \(\frac{n}{s}\) ,此時得到每個塊 \(i\) 的時間復雜度為 \(q_i\cdot s+n+q_i\cdot k\)

  • 所以總時間復雜度為 \(\sum_{i=1}^{n/s} q_i\cdot s+n+q_i\cdot k=m\cdot s+n\cdot \frac{n}{s}+m\cdot k\) 。此時我們發現最后面的一項始終為定值,無法通過改變塊的大小來改變,所以時間復雜度為 \(O(mk)\)

  • 如果分塊呢?我們不妨將兩個塊看成一個整體,表示左右端點在這兩個塊里的一種情況。每個整體 \((i,j)\) 的詢問次數為 \(q_{ij}\) 。但此時整體的總數就不是 \(\frac{n}{s}\) ,而是 \(\left(\frac{n}{s}\right)^2\) 了,對於塊 \((i,j)\) 來說,其復雜度為 \(2\times q_{ij}\cdot s+n\)

  • 所以總時間復雜度為 \(\sum_{i=1}^{(n/s)^2} 2\times q_{ij}\cdot s+n=2\times m\cdot s+n\cdot \frac{n^2}{s^2}\)

  • 這個時候我們發現每一項都與塊的大小 \(s\) 有關,故可以通過選擇一個恰當的塊的大小來得到最優的時間復雜度。

  • \(Update\:(on\:2021.3.15)\::\) 當時可能是腦子抽了……像普通莫隊一樣直接用基本不等式搞上去就好了。

  • 忽略常數並設 \(m=n\) 可得:\(n\cdot s+\frac{n^3}{s^2}\geq \sqrt{\frac{n^4}{s}}\) ,當且僅當 \(n\cdot s=\frac{n^3}{s^2}\Rightarrow s=n^{\frac{2}{3}}\) 時取等。此時 \(\sqrt{\frac{n^4}{s}}=\sqrt{n^{\frac{10}{3}}}=n^{\frac{5}{3}}\)

證畢。

——2021年2月18日


免責聲明!

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



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