掃描線算法
給出幾個矩形對角端點坐標,求這些矩形整體覆蓋的面積。
基本思想如下圖:
- 先離散化。
- 【掃描線】是一根想象中的虛線,從左往右掃描,遇到【矩形】則成為【事件】。
- 遇到【起始邊】,則
Update
相應區間的【厚度】或者【覆蓋次數】CoverCnt+1。 - 遇到【結束邊】,則
Update
相應區間的【厚度】CoverCnt-1。 - 用【線段樹】維護【區間】的厚度CovertCnt,以及區間CovertCnt > 0 的線段的總長度Len。
求面積poj1511
求面積比較簡單:
\[S = \Delta x * \sum_{cnt\gt 0}(raw(i+1)-raw(i)) \]
即可。也就是每次Update后,增加面積即可。
如何處理CovertCnt的不一致?
CovertCnt不一致,出現在“斷點”,即Update后,區間不連續。比如: Range[1-4].CovertCnt=2,現在Update(R[1-2])
, 如何處理?
- 標記為【無效】,查詢時,如果有【無效標記】,則繼續往下查。
- 干脆直接維護SumLen,出現這種情況,由下往上PushUp更新SumLen即可。
從本質上來講,兩者效果差不多,一個是馬上維護SumLen,一個是查詢時再計算SumLen。后者省了一次函數調用,和有可能再次被“全區間覆蓋”時簡化計算,效率能夠高一些。所以熟悉哪種就用哪種,切記切記,會10種不如精一種!
Query時需要pushdown
嗎?
因為查詢的是整個區間,不存在“交叉區間”,所以不需要。(當然PushDown【沒毛病】,如果沒有十足的把握,還是PushDown,反正沒有什么副作用。)
Query,當【查詢區間】和【更新區間】出現【交叉】的時候,需要
PushDown
,比如:更新到:[1-2]
和[3-4]
但要查詢[2-3]
,則只能由[2]``[3]
兩部分構成,所以你必須要從[1-2]
PushDown到[2],從[3-4]
pushdown到[3]
。但如果永遠查詢都是[1-N]
的話,就不存在這種情況。
求周長 hdu1828
道理基本上差不多,稍復雜。
- 兩次掃描,橫向和豎向。
- 每次
Update
后,【周長的增加額】 = abs(【Update前SumLen】-【SumLen】)
\[ \Delta L_i= \sum_{cnt\gt 0}(raw(i+1)-raw(i)) \\ \Delta L = \sum_{i=0}^nAbs(\Delta L_i -\Delta L_{i-1} ) \]
當然也有【一次】掃描的方法,不過需要維護更多的參數,更加復雜一些。一般情況下沒有必要。