首页 > 代码库 > POJ 1151 Atlantis 线段树+离散化

POJ 1151 Atlantis 线段树+离散化

题目链接: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 线段树+离散化