1. 程式人生 > >POJ 1151 Atlantis 線段樹+離散化

POJ 1151 Atlantis 線段樹+離散化

roc 線段樹 aps sin program cal ase gree org

題目鏈接:http://poj.org/problem?id=1151 http://acm.hdu.edu.cn/showproblem.php?pid=1542

題目大意:給你幾個矩形的坐標,求他們的面積的並。

解題思路:可以參考http://www.cnblogs.com/kuangbin/archive/2011/08/16/2140544.html,實際上就是一個方向直接算出,另一個方向使用線段樹維護已經覆蓋的底邊的長度。具體操作不算復雜:假想一條掃描下從下往上開始進行掃描,初始時候沒有邊,線段樹維護的值為0,每次碰到一條底邊,就將這條底邊加入線段樹中並且更新他們覆蓋的總長度,如果碰到頂邊,就將這個邊從線段樹中刪除,而總面積即是每兩條邊之間的面積的總和。

給每條底邊設置個flag = 1,頂邊flag = -1,那麽就容易在線段樹上操作了。

離散化實際上是對每個浮點數坐標離散化。註意的是離散後,線段樹上的中值mid既可以在左孩子又可以在右孩子中。

代碼:

 1 const int maxn = 250;
 2 struct node{
 3     int f;
 4     double rlen, rl, rr;
 5 };
 6 node tree[maxn * 4];
 7 struct Line{
 8     double x1, x2, y;
 9     int flag;
10     bool operator < (const
Line &t) const{ 11 return y < t.y; 12 } 13 Line() {} 14 Line(double a, double b, double c, int f): x1(a), x2(b), y(c), flag(f) {} 15 }; 16 Line lines[maxn]; 17 double ys[maxn]; 18 int n; 19 20 void build(int l, int r, int k){ 21 tree[k].f = 0; tree[k].rl = ys[l]; tree[k].rr = ys[r]; tree[k].rlen = 0
; 22 if(l + 1 == r) return; 23 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1; 24 build(l, mid, lc); 25 build(mid, r, rc); 26 } 27 void cacu(int l, int r, int k){ 28 if(tree[k].f > 0) { 29 tree[k].rlen = tree[k].rr - tree[k].rl; 30 return; 31 } 32 if(l + 1 == r) tree[k].rlen = 0; 33 else tree[k].rlen = tree[k << 1].rlen + tree[k << 1 | 1].rlen; 34 } 35 void update(Line ul, int l, int r, int k){ 36 if(ul.x1 <= tree[k].rl && ul.x2 >= tree[k].rr){ 37 tree[k].f += ul.flag; 38 cacu(l, r, k); 39 return; 40 } 41 if(ul.x1 > tree[k].rr || ul.x2 < tree[k].rl) return; 42 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1;43 if(ul.x2 <= tree[lc].rr) update(ul, l, mid, lc); 44 else if(ul.x1 >= tree[rc].rl) update(ul, mid, r, rc); 45 else{ 46 update(ul, l, mid, lc); 47 update(ul, mid, r, rc); 48 } 49 cacu(l, r, k); 50 } 51 52 int main(){ 53 int t = 1; 54 while(scanf("%d", &n) != EOF && n != 0){ 55 int cnt = 1; 56 for(int i = 1; i <= n; i++){ 57 double x1, x2, y1, y2; 58 scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2); 59 lines[cnt] = Line(x1, x2, y1, 1); 60 ys[cnt] = x1; cnt++; 61 lines[cnt] = Line(x1, x2, y2, -1); 62 ys[cnt] = x2; cnt++; 63 } 64 sort(lines + 1, lines + cnt); 65 sort(ys + 1, ys + cnt); 66 cnt--; 67 build(1, cnt, 1); 68 update(lines[1], 1, cnt, 1); 69 double area = 0; 70 for(int i = 2; i <= cnt; i++){ 71 area += (lines[i].y - lines[i - 1].y) * tree[1].rlen; 72 update(lines[i], 1, cnt, 1); 73 } 74 printf("Test case #%d\nTotal explored area: ", t++); 75 printf("%.2f\n\n", area); 76 } 77 }

題目:

Atlantis
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 23249 Accepted: 8669

Description

There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

Input

The input consists of several test cases. Each test case starts with a line containing a single integer n (1 <= n <= 100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.
The input file is terminated by a line containing a single 0. Don‘t process it.

Output

For each test case, your program should output one section. The first line of each section must be "Test case #k", where k is the number of the test case (starting with 1). The second one must be "Total explored area: a", where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.
Output a blank line after each test case.

Sample Input

2
10 10 20 20
15 15 25 25.5
0

Sample Output

Test case #1
Total explored area: 180.00 

Source

Mid-Central European Regional Contest 2000

POJ 1151 Atlantis 線段樹+離散化