這玩意兒又稱\(segment\ tree\ beats\) 。由吉老師、\(picks\)、美國隊長三位知名毒瘤發明。
我的精神受到了汙染......
線段樹什麼的太難了,不是很會啊.....
線段樹最強的地方在於,如果標記支援合併,那麼我們就能夠快速進行區間修改了。
維護這樣乙個標記\((a,b)\) ,表示\(x\to max(x + a , b)\) 。
顯然標記可合併:\((a,b) + (c,d) = (a + c , max(b + c , d))\) 。
這個標記可以同時處理區間加法、區間覆蓋,對應為\((add,-inf)\)、\((-inf , cov)\) 。
這個標記還能取\(max\):\(max((a,b) , (c,d)) = (max(a,c) , max(b , d))\)
由於該分段函式取上平面交後段數不變,所以支援維護歷史最大值,可以說是相當好用了。
然而這個東西在解決歷史最小值,區間取\(min\)等一系列問題上無能為力,所以我們需要另闢蹊徑。
設當前最大值為\(mx\)、最小值為\(mn\)、修改增量標記為\(t\)。
設歷史最大值為\(hmx\),歷史最小值為\(hmn\)。
直接維護不好維護,我們考慮維護歷史最大標記\(mxt\)、歷史最小標記\(mnt\)。
可以理解為,這個歷史最大標記\(mxt\)是修改標記\(t\)的乙個最大字首和,歷史最小標記\(mnt\)類似。
那麼下放就很簡單了。
先用新的字首和更新所有歷史最優值:
\(mx + mxt' \to hmx\)、\(mn + mnt'\to hmn\)、\(t + mxt' \to mxt\)、\(t + mnt'\to mnt\) 。
然後再把當前值改為真實值:\(t'\to t\)、\(t' + mx \to mx\)、\(t' + mn\to mn\) 。
當然這些標記不一定要是加法標記。
只要是支援合併,並且能夠定義大小關係的標記,我們都可以這麼做。
例題:[uoj164]【清華集訓2015】v ; **
當修改操作逐漸使得元素趨近於相同時,往往就可以搞事情。
目前已知的這類操作:
解決方案就是:若該修改對當前區間影響相同則打標記,否則暴力遞迴處理。
比如,對於開根、除法操作,記錄區間最小、最大值。
對於區間或 + 區間與操作,記錄區間內每一位是否相同(用位運算即可所有位一起實現)。
例題:[bzoj5312]冒險 ; **
[uoj228] 基礎資料結構練習題 ; **
勢能分析之類的略過,反正我口胡的勢能分析連我自己都不知道對不對。
以區間取\(max\)為例。
維護區間最小值\(mn\)、區間次小值\(se\)。
對於區間對\(x\)取\(max\)操作,首先定位到\(log\)個線段樹結點,然後從它們開始\(dfs\)。
設當前點為\(u\)。
若\(x \leq mn_u\) ,顯然該操作對區間無影響,\(return\) 。
若\(mn_u < x < se_u\),我們維護最小值修改標記\(t\),把最小值改為\(x\)即可。
若\(se_u \leq x\) ,暴力遞迴。
顯然加法操作可以直接維護,額外維護乙個標記\(d\)表示最小值之外的其他數的修改量。
注意一點:\(pushdown\)時,若\(se_u = inf\) , 那麼\(se_u\) 不能被修改,因為我們要保證勢能分析時關鍵點的數量。
同時\(pushdown\)的時候,我們要討論兒子的每個值對應哪個標記,進行對應修改。
區間取\(min\)是一樣的,維護區間最大值\(mx\),區間次大值\(se\)即可。
需要注意的一點:
當我們需要同時支援區間\(max\)、區間\(min\)的時候,取\(max\)時要考慮它對最大值的影響,取\(min\)時要考慮它對最小值的影響。
我們的加法標記要分為三類:\(mn.t\)、\(mx.t\)、\(md.t\),分別對應區間最大值增量、區間最小值增量,非最大最小值增量。
一樣的\(pushdown\)時要考慮兒子每乙個值對應的修改應該是哪乙個,然後用其屬於的修改標記進行修改。
例題[bzoj4695] 最假女選手 ; **
[bzoj4355] play-with-sequence ; **
線段樹各種操作大融合。
沒什麼好說的,按照上面的方法乙個乙個實現即可。
**必須模組化,並且是條理清晰的模組化,否則這種題是調不出來的。
例題[uoj169] 元旦老人與數列 ; **
[uoj170] picks loves segment tree viii ; **
關於線段樹
首先肯定推薦學姐部落格!炒雞優秀的學姐!主要是貼 並沒有什麼理論的講解。例題 洛谷p3372 模板 線段樹1 洛谷p3373 模板 線段樹2 線段樹支援單點查詢 單點修改 區間查詢 區間修改等操作。基本思想是二分 將線段樹節點用乙個結構體打包起來 建樹 build 1,1 n void build ...
bzoj4695 最假女選手 吉利線段樹
給出長為n 5e5 的序列,要求支援區間加 區間取min max 區間求和 區間求min max。我 好久好久以前 就想學這個科技 o nlog 2n o n log2 n 的segme nttr eebe ats se gmen ttre ebea ts 區間取min max時,對於被包含的區間,...
關於線段樹基礎
必須 二分法,樹的基礎 拓展 補碼,反碼,移碼,lowbit 了解什麼是線段樹及用途 線段樹,類模板題 just a hook include include include include include using namespace std const int t 100009 struct ...