線段樹常用案例2 矩形面積並

2021-10-19 12:06:56 字數 2459 閱讀 2158

來看一道題目:atlantis

這道題的題意是給定若干個平行於座標軸的矩形,求出這若干個矩形的面積之和,如果有重合的部分,只算一次。

首先考慮暴力的演算法,即遍歷每個矩形,用乙個vis陣列記錄每個點的訪問狀態,最後可以統計出總的面積,這種方法在資料小且邊長為整數的時候適用。

這類問題應該引入掃瞄線來做,下面來講講掃瞄線的概念。

首先得定義掃瞄線 ,掃瞄線就是一條設想的線,它可以是從水平方向上下掃瞄,也可以從豎直方向左右掃瞄,對所有的矩形進行遍歷,計算面積,兩個方向的效果都是一樣的,本文下面所講都是前者的掃瞄方法。

如下圖1.1所示,數字1所標識的是兩個矩形,數字2所標識的是經過掃瞄線的掃瞄,將所有的矩形分成若干個部分來分別計算。虛線就代表掃瞄線,藍色箭頭方向表示掃瞄的方向,我們可以發現,矩形被分割成幾個部分,是取決於矩形的上下邊的 ,每遇到一條上邊或者下邊,就分割出了乙個部分。

明白了掃瞄線的基本概念之後,我們再來討論,再將所有矩形劃分成若干個部分後,到底應該如何計算每個部分的面積。

顯然如果我們將掃瞄線以從下向上的方式來進行掃瞄(如上圖),那麼我們需要記錄每條水平的邊,這樣以掃瞄線的視角來掃瞄每條水平邊的時候,不難想到 ,如果我們記錄了每條水平邊的長度和豎直方向的高之後,我們可以很容易的計算每個部分的高了。

如上圖1.2所示,如果我們記錄了紅色部分的下邊h= 10, 上邊 h= 20,那麼我們將掃瞄線從1掃瞄到2的時候,顯然紅色部分的高可以由兩者之差輕易取得。

現在關鍵在於掃瞄每個部分之後,我們應該如何求出該部分的長度,這裡就用線段樹來維護每個部分的長度,下面講講如何實現

為了實現每次都能動態的得到每個部分的長度,我們需要將每個矩形的下邊記為1,上邊記為-1。因為我們實際上掃瞄到乙個矩形的下邊的時候,我們已經計算了這個部分的面積,所以再次掃瞄到這個矩形的上邊的時候,我們只需要撤銷這個部分的長度即可。

此外,我們還得注意, 由於矩形的長度可以很大,而且可以為浮點數,因此我們需要離散化長度的資料,這樣才能更便於線段樹的構造。

所謂的離散化,就是將一些資料做一下對映(個人理解),使之變得易於處理 。

如下圖1.3所示,我們可以看到矩形的長度有浮點數,所以我們可以將座標10對映為下標1,座標15對映為下標2,座標20對映為下標3,座標25.5對映為下標4,然後將所有座標記錄在乙個陣列中,這樣我們可以只用下標構造線段樹,需要用到實際的值的時候,用下標在陣列中查詢即可。

}sort(x+1, x+m+1); // 橫座標排序

sort(s+1, s+m+1, cmp); // 上下邊排序 1表示下邊

int k = unique(x+1, x+m+1) - x; // 返回不同元素的後乙個位址值

build(1, k-1, 1);

for(int i = 1; i < m; i++)

printf("test case #%d\ntotal explored area: %.2f\n\n", count++, ans);

} return 0;

}

線段樹 矩形面積並

給出n個矩形的左下角和右上角的座標,求矩形面積的並。矩形面積並指的是被矩形覆蓋到的面積和,重疊部分僅算一次。多組輸入,每組首先乙個整數 n,代表矩形的數量 接下來每行四個整數 x1,x2,y1,y2,表示左上角座標 x1,y1 與右下角 x2,y2 每行乙個整數,表示矩形的面積並。input 10 ...

線段樹矩形面積並,面積交,周長並

include include include include using namespace std const int maxn 2000 10 define lson l,mid,rt 1 define rson mid 1,r,rt 1 1 struct rec rec maxn 2 str...

線段樹經典題目 矩形面積

有n 100000 個長方形,並且它的邊長平行於x軸或y軸 範圍50000 求這n個長方形覆蓋的面積,重疊部分的面積只算一次。在平面上的一些統計的題目,往往是用線段樹,把x軸作為掃瞄線,然後把y軸對映到線段樹上。這題也是如此 若座標範圍太大,可以將其離散化,這題不需要。如圖,有兩個矩形。豎細線作為掃...