給出幾個矩形對角端點座標,求這些矩形整體覆蓋的面積。
基本思想如下圖:
先離散化。
【掃瞄線】是一根想象中的虛線,從左往右掃瞄,遇到【矩形】則成為【事件】。
遇到【起始邊】,則update
相應區間的【厚度】或者【覆蓋次數】covercnt+1。
遇到【結束邊】,則update
相應區間的【厚度】covercnt-1。
用【線段樹】維護【區間】的厚度covertcnt,以及區間covertcnt > 0 的線段的總長度len。
求面積比較簡單:
\[s = \delta x * \sum_(raw(i+1)-raw(i))
\]即可。也就是每次update後,增加面積即可。
covertcnt不一致,出現在「斷點」,即update後,區間不連續。比如: range[1-4].covertcnt=2,現在update(r[1-2])
, 如何處理?
標記為【無效】,查詢時,如果有【無效標記】,則繼續往下查。
乾脆直接維護sumlen,出現這種情況,由下往上pushup更新sumlen即可。
從本質上來講,兩者效果差不多,乙個是馬上維護sumlen,乙個是查詢時再計算sumlen。後者省了一次函式呼叫,和有可能再次被「全區間覆蓋」時簡化計算,效率能夠高一些。所以熟悉哪種就用哪種,切記切記,會10種不如精一種!因為查詢的是整個區間,不存在「交叉區間」,所以不需要。(當然pushdown【沒毛病】,如果沒有十足的把握,還是pushdown,反正沒有什麼***。)
query,當【查詢區間】和【更新區間】出現【交叉】的時候,需要道理基本上差不多,稍複雜。pushdown
,比如:更新到:[1-2]
和[3-4]
但要查詢[2-3]
,則只能由[2]``[3]
兩部分構成,所以你必須要從[1-2]
pushdown到[2],從[3-4]
pushdown到[3]
。但如果永遠查詢都是[1-n]
的話,就不存在這種情況。
兩次掃瞄,橫向和豎向。
每次update
後,【周長的增加額】 = abs(【update前sumlen】-【sumlen】)
\[ \delta l_i= \sum_(raw(i+1)-raw(i)) \\
\delta l = \sum_^nabs(\delta l_i -\delta l_ )
\]
當然也有【一次】掃瞄的方法,不過需要維護更多的引數,更加複雜一些。一般情況下沒有必要。
X 掃瞄線演算法
多邊形有兩種重要的表示方法 頂點表示和點陣表示 頂點表示是用多邊形的頂點序列來表示多邊形。這種表示直觀 幾何意義強 佔記憶體少,易於進行幾何變換。但由於它沒有明確指出哪些象素在多邊形內,故不能直接用於面著色 點陣表示是用位於多邊形內的象素集合來刻畫多邊形。這種表示丟失了許多幾何資訊 如邊界 頂點等 ...
區域填充之掃瞄線演算法
區域的填充可以根據區域的填充,採用不同的填充演算法,而其中有掃瞄線類演算法和種子填充演算法。這裡,先介紹掃瞄線類演算法之有序邊表的掃瞄線演算法。其他什麼種子填充 邊界標誌演算法 4連通區域的遞迴演算法 8連通區域的遞迴演算法 掃瞄線種子填充演算法比較簡單。其實有序邊表其實領會了也好理解,關鍵是將思想...
掃瞄線 演算法學習筆記
一般如果是從左往右掃的話,首先用結構體表示圖形 長方形或正方形 的左右兩邊 struct ddu n 2 f 表示該邊時入邊還是出邊,入邊為 1 出邊表示 1 x 表示該邊的x座標,y1 表示該邊的上邊y座標,y2 表示該邊的下邊y座標 如圖 這個還沒完,可以發現y的取值範圍為1 1e9,因為我們線...