掃描線算法


掃描線算法

給出幾個矩形對角端點坐標,求這些矩形整體覆蓋的面積。
基本思想如下圖:

  1. 先離散化。
  2. 【掃描線】是一根想象中的虛線,從左往右掃描,遇到【矩形】則成為【事件】。
  3. 遇到【起始邊】,則 Update 相應區間的【厚度】或者【覆蓋次數】CoverCnt+1。
  4. 遇到【結束邊】,則Update 相應區間的【厚度】CoverCnt-1。
  5. 用【線段樹】維護【區間】的厚度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]), 如何處理?

  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

道理基本上差不多,稍復雜。

  1. 兩次掃描,橫向和豎向。
  2. 每次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} ) \]

當然也有【一次】掃描的方法,不過需要維護更多的參數,更加復雜一些。一般情況下沒有必要。


免責聲明!

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



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