CDQ分治與整體二分
前言
本來想要只講CDQ分治的,但由於整體二分和CDQ分治有一些相似之處,便順藤摸瓜一起講了
在講解之前,先普及一下在線算法和離線算法的定義
在線算法: 可以以序列化的方式一個一個的處理輸入,不必事先知道所有輸入數據
離線算法: 必須事先知道所有的輸入數據 (例如選擇排序就是一個離線算法,而插入排序則不是)
還有一點,在學習算法前掌握凸殼和斜率優化可能會有神助
CDQ分治
CDQ分治,是一種十分優美的暴力算法。它可以代替很多比較玄學的數據結構,乃廣大OIer的福音
但是,不得不感嘆一句,網絡上關於CDQ分治的講解實在是太少,而且語言過於抽象,
這導致很多OIer沒能接觸到其魅力就避而遠之。
CDQ分治的關鍵在於,每個子問題不僅是解決它自身,並且用前一個子問題來求解後一個子問題。常用來將一些動態的問題轉化到靜態來解決,使問題處理起來更加方便。
使用CDQ分治需要滿足一定的條件:
1.題目允許離線操作
2.修改操作對詢問的貢獻獨立,且修改之間互不影響
3.修改對答案的貢獻是確定的,與判定標準無關
4.常數小
揭開這個幌子,先來舉例說明這個算法的特點
1.代碼簡短(比起樹套樹來說)
2.易想出
3.為離線算法(化動態開點為靜態查詢),如果需要強制在線的話還是推薦其它算法
和普通的分治一樣,分和治在這個算法中都得到了很好的展現
1.我們要解決一系列問題,這些問題一般包含修改和查詢操作,可以把這些問題排成一個序列,用一個區間[L,R]表示。
2.分。遞歸處理左邊區間[L,M]和右邊區間[M+1,R]的問題。
3.治。合並兩個子問題,同時考慮到[L,M]內的修改對[M+1,R]內的查詢產生的影響。即,用左邊的子問題幫助解決右邊的子問題。
和很多數據結構(線段樹,樹狀數組。。。)一樣,它做了這麽多是為了什麽?就是為了把符合本次查詢的限制的修改對答案產生的效果合並起來
整體二分
說完了CDQ分治再來說說整體二分
相對於CDQ分治,整體二分的知名度會更高一些,是很多OIer在解決一些問題時的常用方法
整體二分產生的原因:對於單個查詢而言,我們可以采用預處理+二分答案的方法解決,但往往我們要回答的是一系列的查詢,對於每個查詢而言我們都要重新預處理然後二分,時間復雜度無法承受,但是我們仍然希望通過二分答案的思想來解決,整體二分就是基於這樣一種想法——我們將所有操作(包括修改和查詢)一起二分,進行分治
簡單地說,整體二分就是對詢問和答案同時二分
同樣的,整體二分也需要滿足一定的條件:
1. 題目允許離線操作
2. 修改操作對詢問的貢獻獨立,且修改之間互不影響
3. 修改對答案的貢獻是確定的,與判定標準無關
4. 答案具有二分性
5.貢獻滿足交換律,結合律,具有可加性
CDQ分治和整體二分的異同
同:
1.都是按時間進行分治
2.代碼很像(不完全一樣,這在異中會講到)
3.復雜度都是O(f(n)logn)
異:
1.整體二分有二分答案操作
2.適用範圍不同(具體看上面的使用條件)
CDQ分治與整體二分