掃描線算法

掃描線算法

給出幾個矩形對角端點座標,求這些矩形總體覆蓋的面積。
基本思想以下圖:算法

  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]), 如何處理?spa

  1. 標記爲【無效】,查詢時,若是有【無效標記】,則繼續往下查。
  2. 乾脆直接維護SumLen,出現這種狀況,由下往上PushUp更新SumLen便可。code

    從本質上來說,二者效果差很少,一個是立刻維護SumLen,一個是查詢時再計算SumLen。後者省了一次函數調用,和有可能再次被「全區間覆蓋」時簡化計算,效率可以高一些。因此熟悉哪一種就用哪一種,切記切記,會10種不如精一種!blog

    Query時須要pushdown嗎?

由於查詢的是整個區間,不存在「交叉區間」,因此不須要。(固然PushDown【沒毛病】,若是沒有十足的把握,仍是PushDown,反正沒有什麼反作用。)事件

Query,當【查詢區間】和【更新區間】出現【交叉】的時候,須要PushDown,好比:更新到:[1-2][3-4] 但要查詢[2-3] ,則只能由[2]``[3] 兩部分構成,因此你必需要從[1-2]PushDown到[2],從[3-4]pushdown到[3]。但若是永遠查詢都是 [1-N] 的話,就不存在這種狀況。class

求周長 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} ) \]date

    固然也有【一次】掃描的方法,不過須要維護更多的參數,更加複雜一些。通常狀況下沒有必要。方法

相關文章
相關標籤/搜索