分塊算法(簡潔易懂)
分塊
先簡單介紹一下分塊算法。
分塊算法是一種很常見的根號算法,一般它的時間復雜度會帶根號。
分塊和線段樹的區別在於,分塊算法可以維護一些線段樹維護不了的東西,例如單調隊列等,線段樹能維護的東西必須能夠進行信息合並,而分塊則不需要。不過,它們也有共同點,分塊和線段樹一樣,分塊需要支持類似標記合並的東西。
簡單來說,分塊算法就是優化過后的暴力。
現在講一下這種算法的實現。
這種算法會將序列(序列長度為N)進行分塊,通常設置一個上限K,每一塊有至多K個元素。在序列分塊問題上,一般會嚴格要求每個塊都要有K個元素,這樣就會分成約NK塊。(最后一個塊除外)
我們一般都會設K=N−−√,這樣塊數也就只有NK=N−−√塊數可能多一。
通常實現時,我們用bei表示第i個位置所屬的塊。對於每個塊都進行信息維護。
單點修改時,我們一般先將對應塊的標記下傳,再暴力更新被修改塊的狀態。
時間復雜度O(n−−√)。
如果是區間[L,R]修改的話,對於被[L,R]整塊跨過的塊直接打標記,兩端剩余的部分暴力重構塊的狀態即可。
中間最多經過n−−√塊,兩邊暴力修改也是n−−√次的,所以時間復雜度為O(n−−√)。
至於詢問操作,和區間修改類似,對於中間跨過的整塊,直接利用塊保存的信息統計答案,兩端剩余部分任然可以暴力掃描統計。
時間復雜度和區間修改一樣,也是O(n−−√)。
如果詢問次數為m,那總的時間復雜度即為O(mn−−√)。
這就是最簡單的分塊思想,雖然思路很簡單,但實現起來,本人覺得有點復雜。
例題:
BZOJ 2002 Bounce 彈飛綿羊 [Hnoi2010]
網址:http://www.lydsy.com/JudgeOnline/problem.php?id=2002
這是我寫的題解:http://blog.csdn.net/xianhaoming/article/details/52201214
參考:
分塊算法講解 - CSDN博客
http://blog.csdn.net/XianHaoMing/article/details/52201698