引入
在某一類算法流程當中,中間流程十分復雜難以直接分析復雜度。
為了解決這類問題的復雜度分析,我們引入物理中能量守恆的思想來解決此問題。
其本質在於將復雜度刻畫為做功引起勢能變化,而由能量的特性只用管始末狀態而不需要管中間的做工情況,恰好能解決開始所提到的中間流程復雜的問題。
一般地,使用勢能分析得到的大多為均攤復雜度。
簡介
一般模型如下(視情況也可調節):
令第 \(i\) 次操作復雜度消耗為 \(t_i\),第 \(i\) 個狀態為 \(S_i\),狀態 \(S\) 所對應勢能為 \(F(S)\),那么我們將 \(t_i\) 描述為如下形式:
(可以將 \(c_i\) 看作常量做功,\(F(S_i) - F(S_{i - 1})\) 看作勢能變化量,\(t_i\) 為總功)
那么我們有最終復雜度:
一般地,我們需要得出 \(\sum c_i\) 的一個上界,以及 \(F(S_n) - F(S_0)\) 的一個上界,以此確定 \(\sum t_i\) 的一個上界。
簡例
單調隊列復雜度分析
事實上單調隊列復雜度可以簡單地分析,但為了熟悉勢能分析法我們給出如下分析。
令 \(S\) 為單調隊列的一個狀態,\(F(S) = |S|, t_i\) 為第 \(i\) 次操作消耗復雜度,\(c_i\) 為第 \(i\) 次操作入隊數量,\(S_i\) 為第 \(i\) 次操作結束后(出隊結束后)單調隊列的狀態。
那么有:
則總復雜度為:
因此我們也從勢能分析的角度得到了單調隊列復雜度的證明。
並查集啟發式合並復雜度分析
約定
我們記節點 \(x\) 的子樹大小為 \(|x|\),其勢能函數 \(\varphi(x) = \log |x|\)。
顯然並查集只存在兩種操作,於是分兩種操作考慮復雜度。
- \(\tt find\) 操作
顯然單次復雜度 \(\mathcal{O}(1)\),但由於我們不知道調用次數上限,因此只能將其放縮為勢能變化的形式(不帶常數)。
具體地,我們稱簡介中的第 \(i\) 個狀態為 \(\tt find\) 操作中訪問到的第 \(i\) 個節點 \(x\) 那么下一個節點即為 \(x' = fa_x\) 為第 \(i + 1\) 個狀態。
那么就需要將此常數放縮成 \(k(\varphi(x') - \varphi(x))\) 的形式。
由於啟發式合並的特性,我們有:
可知:
那么有單次復雜度變化量:
因此有 \(\tt find\) 操作總復雜度:
- \(\tt Merge\) 操作
顯然 \(\tt Merge\) 操作由兩個 \(\tt find\) 操作及一次 \(\mathcal{O}(1)\) 操作構成,由 \(1\) 的分析可知復雜度為 \(\mathcal{O(\log n)}\)。
Splay 復雜度分析
約定
記小寫字母 \(x\) 為 \(\tt Splay\) 上的一個節點,\(x'\) 為 \(x\) 經過操作變換后對應節點,大寫字母 \(S\) 為一顆 \(\tt Splay\)。
記 \(y\) 為 \(x\) 在 \(\tt Splay\) 上的父親,\(z\) 為 \(y\) 在 \(\tt Splay\) 上的父親,\(|x|\) 為節點 \(x\) 在 \(\tt Splay\) 上子樹的大小。
定義節點 \(x\) 的勢能函數 \(\varphi(x) = \log |x|, \mathtt{Splay} \ S\) 的勢能函數為 \(\phi(S) = \sum\limits_{x \in S} \varphi(x)\)。
下面我們證明 \(\tt Splay\) 單次將節點 \(x\) 旋到根的復雜度為 \(\mathcal{O(\log n)}\) 其他操作均可視為該操作的組合。
對於 \(\tt Splay\) 雙旋的兩種情況我們考慮分別將復雜度增量描述為勢能變化量。
同時,由於單次旋轉復雜度 \(\mathcal{O(1)}\) 很難描述為勢能變化量,因此我們考慮將單次旋轉復雜度描述為:\(\mathcal{O(1)} + \Delta \phi(S)\)
得到兩者和的上界再考慮減去 \(\phi(S)\) 總變化量下界即可,由定義可知,總變化量:
因此可以將修改后計算出的復雜度加上 \(n \log n\) 即可,不影響總復雜度。
- 若 \(x, y, z\) 三點共線
有總勢能變化量:
又我們將復雜度描述為 \(\mathcal{O}(1) + \Delta \phi(S)\),我們並不好衡量常數之和,因此盡量將其放縮為不存在常量的勢能變化量。
顯然不能將上界放縮成 \(\Delta \phi(S)\) 的形式,因此只能將上界放縮為 \(k(\varphi(x') - \varphi(x)), k\) 為常數的形式。
據此,考慮將復雜度表達式放縮引入 \(\varphi(x')\) 並盡可能化簡式子。
同時,為了方便我們直接將 \(\mathcal{O}(1)\) 看作 \(1\),最后直接乘該常量即可。
考慮借助勢能關系放縮 \(1\),我們有:
進一步有:
帶入原式:
旋轉結束后,可得總復雜度 \(< 3(\varphi(root) - \varphi(x_0)) < 3\log n\) 得證。
- 若 \(x, y, z\) 三點不共線
同樣有:
注意,此時我們所擁有的條件變化,因此不像上一種情況一樣放縮。
具體地,我們有:
類似地,可以得到:
那么有:
旋轉結束后,可得總復雜度 \(< 2(\varphi(root) - \varphi(x_0)) < 2\log n\) 得證。
由此,我們得到了 \(\tt Splay\) 的復雜度為 \(\mathcal{O((n + m) \log n)}\)。
LCT 復雜度分析
顯然 \(\tt LCT\) 復雜度只來源於 \(\tt Access\) 操作,而 \(\tt Access\) 操作的復雜度來源又可以分為如下兩個部分:
- 虛實兒子切鏈
- 實鏈上 \(\tt Splay\)
由於這兩個部分互不干擾,因此將復雜度分析分開考慮。
虛實兒子切鏈復雜度
首先將樹進行重鏈剖分,稱既為原樹重邊也為 \(\tt LCT\) 中虛邊的邊成為重虛邊,其余類似。
設置整體勢能函數 \(\phi(S)\) 為 \(\mathtt{LCT} : S\) 中的 重虛邊 數量。
考慮 \(\tt Access\) 過程中勢能函數的變化,有如下兩種:
- 勢能函數增加 \(1\),當且僅當當前切換鏈為 輕虛邊,原實邊為重邊。由重鏈剖分理論,單次 \(\tt Access\) 該情況次數不超過 \(\log n\)。
- 勢能函數減少 \(1\),當且僅當當前切換鏈為 重虛邊,原實邊為輕邊。
由 \(1\) 我們有:
因為有勢能函數非負,因此有:
顯然總復雜度:
因此切鏈復雜度是 \(\mathcal{O(n + m \log n)}\) 的。
實鏈 Splay 復雜度
沿用 \(\tt Splay\) 復雜度的分析方式,假設在第 \(i\) 條實鏈內部 \(\tt Splay\) 復雜度為 \(k(\varphi(root_i) - \varphi(x_{0_i}))\)。
顯然有:
因此總復雜度:
結合兩者,有 \(\tt LCT\) 復雜度 \(\mathcal{O((n + m)\log n)}\)
基本分析方式
結合上述四個經典勢能分析,我們可以發現勢能分析應用時的兩種情況:
-
復雜度證明並不依賴於勢能變化量(證明不依賴於操作對勢能的影響),大多數情況下可以被一般方法代替,例如 \(1, 2\)。
-
復雜度證明強依賴於勢能變化量(證明依賴於操作對勢能的影響),一般這類情況是勢能分析的專場,例如 \(3, 4\)。
對於 \(1\),若需要進行勢能分析,往往 只需要 將復雜度描述為勢能變化量再考慮始末勢能變化量即可,且多數情況下該變化量與操作無關,只於實際問題上界有關。
對於 \(2\),需要我們在復雜度描述中引入勢能總體變化量,因為這樣才方便勢能的攤還。
具體來說,將進行單次操作或可簡單分析上界的操作對總勢能貢獻為 \(+\),將多次操作或無法分析上界的操作對總勢能貢獻為 \(-\)。
這樣根據勢能函數的非負性,可以得到貢獻 \(-\) 的操作復雜度與貢獻 \(+\) 的操作復雜度之間的關系從而進行求解,例如 \(\tt LCT\) 中切鏈復雜度的分析。
還有一種比較復雜度的情況,通過引入整體勢能函數無法簡單證明,這時我們就需要引入局部勢能函數。
一般對於 后者 描述為勢能變化量的形式以放縮開始引入的整體勢能函數分析單次操作復雜度。
簡單練習
二進制加法
模擬二進制下的加法,從 \(0\) 開始不斷 \(+1\) 直到 \(n\),每次的操作為 \(\mathcal{O}(1)\) 修改一個位置的數。
顯然加法過程中 \(01\) 有別,因此我們將二進制數划分成極大的 \(01\) 段。
一種簡單的想法是令勢能函數為這樣的段數,但發現無法用段數描述復雜度。
於是考慮修改划分方式,我們將一個單獨的 \(0\) 看作一段,極長的 \(1\) 還是看作一段。
令 \(\varphi(x)\) 為數字 \(x\) 以上述方式划分的段數,分析一下各種情況下 \(\varphi(x)\) 的變化量:
- 形如:\(\cdots 1 \cdots 10\) 則易知 \(\varphi(x + 1) = \varphi(x) - 1\)
- 形如:\(\cdots 00\) 易知 \(\varphi(x + 1) = \varphi(x)\)
- 形如:\(\cdots 001 \cdots 1\)(最后一段 \(1\) 的個數為 \(k\))易知 \(\varphi(x + 1) = \varphi(x) + k - 1\)
- 形如:\(\cdots 1 \cdots 101 \cdots 1\)(最后一段 \(1\) 的個數為 \(k\))易知 \(\varphi(x + 1) = \varphi(x) + k - 2\)
接下來存在兩種證法:
直接利用勢能變化量放縮復雜度
可知上述四種情況復雜度依次為:\(\mathcal{O}(1), \mathcal{O}(1), \mathcal{O}(k + 1), \mathcal{O}(k + 1)\)
則我們有單次復雜度的一個上界:\(\varphi(S + 1) - \varphi(S) + 3\),因此有總復雜度:
借助勢能函數有界性
觀察勢能函數的減少量,可知單次至多減少 \(1\),同時任意時刻我們有界:
假設復雜度增加量之和為:\(\Delta T ^ + \ge 0\) 減少量 絕對值 之和為 \(\Delta T ^ - \ge 0\),那么有:
由於減少量之和 \(\Delta T ^ - \le n\) 因此有總復雜度:
並查集路徑壓縮
還不會,先咕着......
並查集路徑壓縮 + 啟發式合並
也不會,先咕着......