掃描線

一種求多個矩形和周長\(∪\)的方法數組

掃描線:假設有一條掃描線從一個圖形的下方掃向上方(或者左方掃到右方),那麼經過分析掃描線被圖形截得的線段就能得到所要的結果。該過程能夠用線段樹實現——洛谷題解spa

面積並

二話不說先上圖——本身畫圖賊醜,因此暫且借一下洛谷的圖blog

如何求上面兩個矩形的面積呢??排序

咱們假設一條掃描線從下方開始向上掃,掃到橫邊的時候中止、class

首先咱們將矩形的上下邊分爲上位邊(即y座標大的那條平行於x軸的邊),和下位邊(y座標小的平行於x軸的邊).而後咱們把全部矩形的上下位邊按照他們y座標從小到大排序,能夠獲得4條掃描線:方法

根據圖能夠看出,對圖形面積有貢獻的是橫邊左右端點的座標,咱們把矩形的下邊賦予權值爲1,上邊爲-1,而後把全部的邊按照縱座標大小升序排序(模擬掃描過程);im

而後捏??查詢

線段樹是個好東西(每次都掛img

咱們把全部的邊離散化,把橫座標存到一個數組裏,升序排列,而後去重(防止x爲浮點數且很大沒法進行線段樹)兼容

上圖能夠看出,四個橫座標把x軸分紅了5段,咱們取中間3段間線段樹維護

其中每一個端點維護每一個線段信息:

1.該線段被覆蓋了多少次(被多少個矩形所覆蓋)
2.該線段內被整個圖形所截的長度是多少

顯然,只要一條線段被覆蓋,那麼它確定被圖形所截。因此,整個問題就轉化爲了一個區間查詢問題,即:每次將 當前掃描線掃到的邊 對應的信息 按照以前賦上的權值更新,而後再查詢線段樹根節點的信息,最後獲得當前掃描線掃過的面積。這就能夠用線段樹來實現了

模擬過程

咱們已經知道,這棵線段樹的每一個節點都對應了一條線段。考慮將線段樹上節點對應的區間和橫邊創建映射關係。先看對於一個葉子節點\(x\),建樹時保證了\(tree[x].l=tree[x].r\)但其保存的信息很顯然不可能只是某條線段的一個端點(若是一條線段的兩個端點重合,那麼它實質上僅是一個點)。再看一個節點的左右兒子,一樣地,建樹的時候已經保證了左右兒子的區間不會重合(交集爲空),可是看這樣兩條相鄰線段:\([1,2],[2,3]\)你會發現\([1,2]∩[2,3]={2}\),也就是說左兒子的右端點和右兒子的左端點實際上是重合的。

考慮把線段樹每一個節點\(x\)對應的區間\((tree[x].l,tree[x].r)\)不變,改變區間和橫邊的映射關係,具體爲:節點\(x\)對應\([X[tree[x].l],X[tree[x].r+1]]\)這條橫邊。能夠看到,這裏很機智地把右端點的對應關係給改了下,因而就兼容了

相關文章
相關標籤/搜索