###### tags: `MDCPP講義` # 講義-線段樹-區間修改 **Author : 謝侑哲** --- 先來複習一下之前的內容 ---- 線段樹的功能是甚麼? ---- 維護動態的區間值 ---- 線段樹的核心想法是甚麼? ---- 二分搜、DFS、小區間合併成大區間 ---- 做一次單點修改的時間複雜度? ---- O(logN) ![](https://i.imgur.com/92J1CmU.png) ---- 複習完啦,那讓我們進入正題 --- 區間修改 ---- 以你們目前學到的東西 如果要做到區間修改你們會怎麼做? ---- 把一個區間的每個點都做一次區間修改? ---- 他的時間複雜度會是多少? ---- O(NlogN) ---- 雖然看起來還不錯,但或許還能更好? --- 懶人標記 ---- 懶人標記 顧名思義是給懶人用的東西 ---- 懶人?想到甚麼? ---- - 盡可能地做更少事情 - 能拖的事情一拖再拖 ---- 這些就是懶人標記的核心理念 - 把修改的工作變得越少越好 - 把修改的工作一拖再拖 ---- 要怎麼做到? ---- 或許我們可以不用修改區間內每個數的值? ---- [3,6]區間通通+1? ![](https://i.imgur.com/VNuExaT.png) ---- ![](https://i.imgur.com/Z80jEk4.png) 總共用了4次logN ---- 找到最低限度描述區間的塊數 ![](https://i.imgur.com/j4JzEGJ.png) 用了2次logN ---- 這樣的話,要查詢[2,3]區間怎麼辦 ![](https://i.imgur.com/j4JzEGJ.png) ---- 來看看我們查詢的路徑 ![](https://i.imgur.com/7TqUim1.png) ---- 可以發現一件事 查詢的時候,最終還是會經過上層抵達到下層 ![](https://i.imgur.com/7TqUim1.png) 這樣當我們要用到應該被修改得更小區間時 必定會經過被我們加過值的那個區間 ---- 既然修改跟查詢都會走同個路徑抵達同個點 那我們不如把它和在一起做? ---- 在經過某個區間往下時,判斷該區間是否被修改,有則將修改值下傳 ![](https://i.imgur.com/j4JzEGJ.png =650x) ![](https://i.imgur.com/7TqUim1.png =650x) ---- 這樣的複雜度會是多少? ---- 因為查詢時修改是順便做的事情 因此基本上不列入複雜度的計算 ---- 最糟的情況 ---- 以區間長8為例 ![](https://i.imgur.com/kiDhG2h.png) ---- 讓我們稍微移動一下他 ---- 是不是有一種分兩半分兩半再分兩半的味道 ![](https://i.imgur.com/23GFWR4.png) 所以最後出來的複雜度會是O(logN) 比起對每個點做一次修改的O(NlogN)快了N倍 ---- 知道了概念,接下來就是怎麼寫了呢 --- code時間 ---- ```cpp= ``` ----
{"metaMigratedAt":"2023-06-17T01:10:13.672Z","metaMigratedFrom":"Content","title":"講義-線段樹-區間修改","breaks":true,"contributors":"[{\"id\":\"f547d745-63f3-4bad-986b-1751eeec19d1\",\"add\":1480,\"del\":36}]"}
    165 views
   Owned this note