POJ1151 Atlantis 掃瞄線演算法

2022-06-30 08:09:07 字數 2505 閱讀 2416

給出幾個矩形對角端點座標,求這些矩形整體覆蓋的面積。

整個平面被每個矩形的水平邊所在直線(以後簡稱「水平線」)分成了幾個部分,而整體覆蓋面積則為每相鄰的兩個水平線間夾的長度(以後簡稱「夾長」)以及水平線所對應的乙個或幾個矩形水平邊(以後簡稱「水平線段」)在水平線中所佔的長度之積的和。於是我們假設有乙個掃瞄線從下往上掃。由排序得到夾長很容易,但是水平線段長就要用線段樹了。

水平線段在兩個點[l,r]之間所佔的長度coverlen。

運用離散化將double對映成整型排名。

注意事項

在把sorteddata的初值全部設為0時,要考慮到l,r可能是0。這樣在設定rank陣列時,0所對應的排名就成了0,最後線段樹爆棧導致re。所以要讓sorteddata[0] = -1。

既然結點維護的格仔是離散化後的排名,有了排名,原先的長度自然也就知道了。

把兩點之間的區間作為線段樹所維護的格仔即可。線段樹中格仔p表示離散化後排名為p的點和p+1兩個點之間的區間。(所以對線段樹操作時,輸入的r要-1)。

注意事項

為了使魯棒性更高,防止出現「乙個矩形就是乙個豎直線」導致ar==al-1的情況,此時要及時返回。

注意事項

判斷是否pushdown要看該結點是否有deltatag標記,而乙個結點是否在最底層這個標記無論是否有deltatag都要設定。

在乙個結點中,如果乙個結點所負責的區間是乙個水平線段的子區間,且該結點的父節點不是水平線段的子區間,則該結點所負責的區間為該水平線段的極大子區間。我們用covercnt表示:滿足該節點維護的區間是乙個水平線段的極大子區間的水平線段的個數。如果該結點的covercnt>0,則該結點負責的區間必然全部覆蓋;如果covercnt==0,則該節點內的水平線段長就等於兩個子區間的水平線段長之和。特別地,如果該節點是葉子結點,則它所負責的區間內的水平線段長就是0。

根據此時covercnt的定義,我們不用(無法)pushdown。

注意事項:

如果要通過乙個乙個賦值來初始化線段樹,迴圈終止條件不是n,要初始化就徹底一點。

#include #include #include #include #include using namespace std;

const int max_area = 110, max_line = max_area * 2,

max_p = max_line * 2, max_node = max_p * 4;

struct horline

bool operator < (const horline& a)const

}_lines[max_line];

struct discret

return l;

} int lowerboundbyrank(int l, int r, int k)

return l;

}public:

int rankcnt;

void init(double *a, int n)

rankcnt = currank;

} int getrankbyval(double val)

double getvalbyrank(int rank)

}g;struct rangetree

void getlen(int l, int r)

}_nodes[max_node];

void updatenode(int cur, int l, int r, int delta)

void update(int cur, int sl, int sr, int al, int ar, int delta)

int mid = (sl + sr) / 2;

if (al <= mid)

update(cur * 2, sl, mid, al, ar, delta);

if (ar > mid)

update(cur * 2 + 1, mid + 1, sr, al, ar, delta);

updatenode(cur, sl, sr, 0);

} double query(int cur, int sl, int sr, int al, int ar)

public:

rangetree(discret* dis)

void init(int n)

void update(int l, int r, int delta)

double query(int l, int r)

}h(&g);

int main()

sort(_lines + 1, _lines + areacnt * 2 + 1);

g.init(pexist, areacnt * 2);

h.init(g.rankcnt);

double ans = 0;

for (int i = 1; i <= areacnt * 2; i++)

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

}}

POJ1151 Atlantis 矩形切割

給出n個矩形,求這些矩形面積的並。輸入包含多組測試資料 每組資料的第一行包含乙個整數n 1 n 1000 表示矩形的個數。接下來n行,每行四個數 不一定是整數 x1,y1,x2,y2 0 x1最後一行以0作為檔案的結束。對於每組測試資料,輸出兩行 第一行是 test case k k是組數 開始為1...

離散化 蠻力 POJ 1151 Atlantis

題意 求矩形面積並 分析 本來是要學習掃瞄線的,不過還沒看懂。囧。在看了黑書之後,發現這題資料規模如此小 100個矩形 於是yy出了一種方法 1.首先把x,y座標都進行離散化。2.離散化之後,將整個平面劃分成很多面積不等的小矩形。3.列舉每個大矩形,得到大矩形離散化後的左上角點和右下角點的位置。4....

POJ 1151 Atlantis 離散化 暴力

題目鏈結 資料範圍較小,直接離散後暴力。等等學習一下線段樹的思路。1 include 2 include 3 include 4 include 5 using namespace std 6 define n 101 7 define eps 1e 6 8double xr n xc n yr n...