李超樹學習筆記

先說一些題外話

其實很早就有這些這個的慾望了。。。php

可是因爲種種緣由(包括班主任),一直咕到如今。。。html

咕咕咕。。。算法

不能再咕下去了!數據結構

因而熬夜來寫這個。函數

步入正題

先看一個例題:BZOJ1568: [JSOI2008]Blue Mary開公司post

其實這個算是裸題了。。。
固然我作的第一道李超樹的題不是這個。。。
題目要求區間內的全部直線的最高點的最大值。
而且帶插入。
裸的暴力$O(nm)$對吧。
而後呢?
第一想法是——分治!
將一個區間$[l,r]$分紅$[l,mid],[mid+1,r]$兩個區間,遞歸求解。
合併答案就取最大值就好。
這樣,咱們便得出來一個$O(mn\log_2n)$的算法。。。
你會說:「這個算法複雜度還沒暴力跑得快,我要他幹嗎???」
誠然,暴力跑得比它快得多。。。
可是你以爲這個算法若是沒有用的話,我會講它嗎?
咱們回頭看咱們分治的過程:將區間一分爲二,且區間大小相等。
若是你有 像我同樣的超高的$DS$水平,你就會發現這個過程和某個數據結構的過程好像啊!
沒錯!這個數據結構就是—— 線段樹
是否是很厲害!
爲何?由於咱們找到了一種數據結構來維護這玩意了!
因此線段樹每一個點存區間最大值就好。
$BUT$!這麼作還有一個問題:插入線段怎麼辦?
你會想:用最大值覆蓋不就行了?
那麼問題又來了:線段是有斜率的。
也就是說,在不一樣的點,線段的函數值是不一樣的。
你怎麼知道當前的點的函數值是多少呢?
可能你又會想:那我就暴力帶值進線段,把函數值算出來不就行了?
那麼恭喜,你離深淵愈來愈近了。
你會發現你的每一次維護都會涉及到最多$4n$個節點。
那和暴力有什麼區別???
因此這個方案被咱們捨棄了。
那怎麼辦呢?
對於這個問題, 國家隊隊爺李超提出一種解決辦法:
咱們把線段樹中存的值從區間最大值改成 區間中值最大的直線
每一個節點至少會存一條直線。
可是多條直線呢?
咱們能夠打一個標記,說明再這個區間內至少有一個兩條直線的轉折點。
而後遞歸插入直線。
具體作法是這樣的:
假設原來在$[l,r]$這個區間內只有一條直線$f_1(x)=k_1x+b_1$。
如今要在區間內插入一條新直線$f_2(x)=k_2x+b_2$。
而後即是分類討論:

1. 若是$f_1(l)\geq f_2(l),f_1(r)\geq f_2(r)$:ui

說明$f_2(x)$在這個區間內被$f_1(x)$吊打,那麼不作任何操做;url

2. 若是$f_1(l)\leq f_2(l),f_1(r)\leq f_2(r)$:spa

說明$f_1(x)$在這個區間內被$f_2(x)$吊打,那麼直接替換便可;3d

3. 若是$f_1(l)\geq f_2(l),f_1(r)\leq f_2(r)\text{或者}f_1(l)\leq f_2(l),f_1(r)\geq f_2(r)$:
說明兩直線在這個區間內有交點。
這時,咱們取區間中點$mid$,判斷兩直線在$[l,mid]$之間是否相交:
如果,則右區間$[mid+1,r]$賦爲在上方的曲線,左區間遞歸求解;
不然,左區間$[l,mid]$賦爲在上方的曲線,右區間遞歸求解。
這樣,咱們的一次插入直線操做完成。
而遞歸修改最多會涉及到$\log_2n$個節點。
因此一次修改的複雜度上限爲$O(\log_2^2n)$。
而後,這題還須要用到標記永久化。
即咱們不下傳標記,在求區間最大值的時候,每次訪問到一個被詢問區間包含的區間,把答案和這個區間所維護的線段的最大值取$max$。
而後這個題就作完了。
不得不說很是的機智啊!
因此這種線段樹被稱爲—— 李超樹
複雜度$O(m\log_2^2n)$。
瘋狂維護半平面交。。。
代碼的話。。。能夠去題解裏找:

BZOJ1568: [JSOI2008]Blue Mary開公司

再推薦兩道練手題:

相似的板子題:

BZOJ3165: [Heoi2013]Segment

我作的第一道李超樹題:(萬事開頭難。。。)

BZOJ4515: [Sdoi2016]遊戲

後記

其實李超樹不建議在考場上寫。
由於這玩意的修改很容易寫炸。。。
而且查錯及其噁心。。。
對於大多數$DS$能力不是極其強悍的$OIer$來講,性價比並非很高。
由於通常這種題的部分分都比正解的性價比高。。。
因此不是隊爺不寫正解。。。
而對於我這個菜雞$AFO$選手來講,能夠浪一浪。。。
出題人,我勸你善良。。。
相關文章
相關標籤/搜索