李超線段樹


李超線段樹

因為太弱了,所以只會用單調隊列、CDQ分治、平衡樹來維護凸殼,然后被\(zjp\_shadow\)聚聚在博客底下給D了一頓,所以辣雞yyb就來學一下了。
(似乎整個機房就我不會了)

首先先明白這個東西在干啥

你要資磁動態維護一個平面直角坐標系,資磁在中間插入一條線段,資磁詢問與\(x=x0\)這條直線相交的所有線段中,交點的\(y\)軸坐標的最大(小)值。

我們要維護的東西是這個:維護這個區間內的所有直線中,從上往下能夠看到的最長的那個線段,也就是沒有被其他直線覆蓋長度最大的段。

考慮怎么插入一條直線,假設它當前處理到了某個區間:

  • 如果這個區間沒有記錄最長的線段,那么直接把這個區間記錄的線段修改為這條線段,然后返回。
  • 如果當前線段在這個區間內已經被這個區間內的最長線段為覆蓋,那么直接\(gg\),返回就好了。
  • 反過來,如果完全覆蓋了之前記錄的線段,那么直接賦值、返回。
  • 否則和已經記錄的直線有交,判斷哪根線段覆蓋的區域較長,把這個區間記錄的值給修改一下,然后把短的那一半丟下去遞歸。

這樣子復雜度是啥呢?顯然維護復雜度看起來不太對的就是最后一項,但是不難證明每次遞歸下去直線長度都至少要減少一半,所以這個東西的復雜度就是一個\(log\)的。
至於詢問?那就是單點詢問啦,在線段樹上一直走到這個單點為之,把路徑上所有記錄的線段拿出來取一個\(max\)就好啦。

比如BZOJ1568就是模板題QwQ。
當然了,上面這題是每次插入一條直線,這樣子只需要一個\(log\),如果每次插入一條線段的話還是要稍微變一下的,即要先找到對應的區間再在這個區間內插入這個線段,這樣子復雜度是兩個\(log\)的,代碼戳這里


然后\(zjp\)說可以用李超線段樹直接維護斜率優化,想了想的確可以,我這里隨便搬一道題目過來。

[HNOI2010]玩具裝箱

首先寫暴力\(O(n^2)\)的轉移,設\(S_i\)\(C_i\)的前綴和。

\[f[i]=\min_{j=0}^{i-1}f[j]+(i-j-1+S_i-S_j-L)^2 \]

\[f[i]=\min_{j=0}^{i-1}f[j]+(i-j-1)^2+(S_i-S_j-L)^2+2(i-j-1)(S_i-S_j-L) \]

然后把式子拆開,和\(j\)無關的直接移出去,只和\(j\)相關的放在一起,同時和\(i,j\)相關的放在一起。
那么分類之后就是這樣的:
\(j\)無關的:\(i^2-2i+1+S_i^2+L^2-2LS_i+2iS_i-2iL-2S_i+2L\)
只和\(j\)有關的:\(f[j]+j^2+2j+S_{j}^2+2LS_j+2jS_j+2jL+2S_j\)
同時和\(i,j\)相關的:\(-2ij-2S_iS_j-2iS_j-2jS_i=-2(i+S_i)(j+S_j)\)
一共\(22\)項,似乎沒有什么問題。(其實可以直接令\(M_i=i-1+S_i-L\),但是為了鍛煉拆式子能力就這樣吧......算了,我編不下去了.....)
那么把和\(j\)無關的部分記做\(pre[i]\),只和\(j\)有關的記做\(y[j]\)\(j+S_j\)記做\(x[j]\)\(2(i+S_i)\)記做\(k_i\)
那么轉移方程可以改寫成:

\[f[i]=pre[i]+\min_{j=0}^{i-1}(-k_ix[j]+y[j]) \]

\(k_i\)是一個常數,我們把后面這個式子理解為一個一次函數\(y=kx+b\)的形式,得到\(b=y-kx\)
什么意思呢?平面上有若干個點\((x[j],y[j])\),你要過這些點畫一條斜率為\(k_i\)的直線,使得其截距最小。
不難發現滿足條件的\(j\)一定在下凸殼上。
這里有個很優秀的性質,也就是\(k_i,x[j]\)都是單增的。
這樣子凸殼可以直接用單調隊列維護,而取最優值只需要每次找到凸殼左側最優位置就好啦。

上面是直接用斜率優化,然后單調隊列維護凸殼的做法(我直接從別的文章里蒯過來的)
那么我們把那個式子換一下,把\(y[j]\)寫成\(b[j]\)\(-x[j]\)寫成\(k[j]\)
那么轉移就是

\[f[i]=pre[i]+\min_{j=0}^{i-1}2(i+S_i)k[j]+b[j] \]

於是問題變成了,平面上有若干條直線,現在你要詢問在\(x=2(i+S_i)\)處的最小值,所以可以直接使用李超線段樹來維護。(雖然復雜度多了一個\(log\))。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM