【POJ1151】【扫描线+线段树】Atlantis

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

【分析】

扫描线的基本应用,离散化一下按横坐标从左到右扫就行了。

  1 /*
  2 元稹
  3 《离思五首·其四》
  4
  5 曾经沧海难为水,除却巫山不是云。
  6 取次花丛懒回顾,半缘修道半缘君。
  7 */
  8 #include <iostream>
  9 #include <cstdio>
 10 #include <algorithm>
 11 #include <cstring>
 12 #include <vector>
 13 #include <utility>
 14 #include <iomanip>
 15 #include <string>
 16 #include <cmath>
 17 #include <queue>
 18 #include <assert.h>
 19 #include <map>
 20 #include <ctime>
 21 #include <cstdlib>
 22 #include <stack>
 23 #define LOCAL
 24 const int MAXN = 10000 + 10;
 25 const int MAXM = 75 + 10;
 26 const int INF = 100000000;
 27 const int SIZE = 450;
 28 const int maxnode =  0x7fffffff + 10;
 29 using namespace std;
 30 struct Line{//扫描线
 31        int flag;//表示是出线还是入线
 32        double x, y1, y2;
 33
 34        Line (double a, double b, double c, double d){
 35             flag = (int)d;
 36             x = a;
 37             y1 = b;
 38             y2 = c;
 39        }
 40        bool operator < (const Line &b)const{
 41             return x < b.x;
 42        };
 43 };
 44 struct Seg_Tree{
 45        struct Node{
 46               int l, r, flag;
 47               double ll, rr, len;
 48        }tree[2000];
 49        vector<double>y, data;
 50        vector<Line>line;
 51        map<double, int>Map;//离散化
 52
 53        void update(int t, int s, int e, int val){
 54             int l = tree[t].l, r = tree[t].r;
 55             if ((l + 1) == r) {
 56                tree[t].flag += val;
 57                if (tree[t].flag == 0) tree[t].len = 0;
 58                else tree[t].len = tree[t].rr - tree[t].ll;
 59             }
 60             else{
 61                  int mid = (l + r)>>1;
 62                  if (s < mid) update(t << 1, s, e, val);
 63                  if (e > mid) update((t << 1) | 1, s, e, val);
 64                  tree[t].len = tree[t << 1].len + tree[(t << 1) | 1].len;
 65
 66             }
 67        }
 68        void build(int t, int l, int r){
 69             tree[t].l = l;
 70             tree[t].r = r;
 71             tree[t].flag = 0;
 72             tree[t].len = 0;
 73             //这两个是代表真实的值
 74             tree[t].ll = y[l];
 75             tree[t].rr = y[r];
 76             if ((l + 1) == r) return;
 77             //左闭右开
 78             int mid = (l + r)>>1;
 79             build((t<<1), l, mid);
 80             build((t<<1) | 1, mid, r);
 81        }
 82        void init(){
 83             Map.clear();;
 84             line.clear();
 85             y.clear();
 86             data.clear();
 87        }
 88 }A;
 89 int n;
 90
 91 void init(){
 92      A.init();
 93      for (int i = 1; i <= n; i++){
 94          double x1, x2, y1, y2;
 95          scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
 96          A.line.push_back(Line(x1, y1, y2, 1));//1代表入线
 97          A.line.push_back(Line(x2, y1, y2, -1));
 98          A.data.push_back(y1);
 99          A.data.push_back(y2);
100      }
101      int cnt = 0;//离散化
102      sort(A.data.begin(), A.data.end());
103      for (int i = 0; i < A.data.size(); i++){
104          if (i == 0 || A.data[i] != A.data[i - 1]){
105             A.Map[A.data[i]] = cnt++;
106             A.y.push_back(A.data[i]);
107          }
108      }
109 }
110 void work(){
111      sort(A.line.begin(), A.line.end());
112      A.build(1, 0, A.y.size() - 1);
113      double Ans = 0;
114      for (int i = 0; i < A.line.size(); i++){
115          if (i != 0) Ans += (A.line[i].x - A.line[i - 1].x) * A.tree[1].len;
116          A.update(1, A.Map[A.line[i].y1], A.Map[A.line[i].y2], A.line[i].flag);
117      }
118      printf("Total explored area: %.2lf\n\n" , Ans);
119 }
120
121 int main(){
122
123     int t = 0;
124     while (scanf("%d", &n) && n){
125           printf("Test case #%d\n", ++t);
126           init();
127           work();
128     }
129     return 0;
130 }

时间: 2024-10-24 15:28:15

【POJ1151】【扫描线+线段树】Atlantis的相关文章

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

poj 1151 Atlantis (离散化 + 扫描线 + 线段树)

题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #define LL __int64 8 #define lson l, mid, 2*rt

hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> #include <algorithm> #define MAXN 110 #define LL ((rt<<1)+1) #define RR ((rt<<1)+2) using namespace std; int n; struct segment{ double l

HDU1542_Atlantis(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求矩形并面积. 思路: 离散+线段树+扫描线. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { int v; double h,lx,rx; friend bool operator < (Seg a,Seg b) { return a.h<b

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

HDU3265_Posters(扫描线/线段树)

解题报告 题意: 给定的矩形里面有镂空的矩阵,求矩阵面积并. 思路: 直接把一个图形拆成4个矩形,进行面积并. 扫描线+线段树 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #define LL __int64 using namespace std; struct Seg { int lx,rx,h,v; friend bool operator

HDU1377_Counting Squares(扫描线/线段树)

解题报告 题意: 矩形面积并. 思路: 扫描线+线段树 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { int lx,rx,h,v; friend bool operator < (Seg a,Seg b) { return a.h<b.h; } } seg[500000]

HDU 1255 覆盖的面积 (扫描线 线段树 离散化)

题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了,因为虽然现在都不等于 2,但是之前的那个线段加上现在的已经覆盖2次了. 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include &

HNU12884_Area Coverage(扫描线/线段树+离散化)

解题报告 题目传送门 题意: 又是求面积并 思路: 又是求面积并,还被坑了,题目明明描述的是int坐标,用了double才过... #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> using namespace std; struct Seg { double lx,rx,h; int v; friend bool operator <(Seg

HDU1255_覆盖的面积(扫描线/线段树+离散)

解题报告 题目传送门 题意: 求面积交. 思路: 不会呀. 只知道线段树应该维护覆盖数大于2的线段长度. 不会更新,看了别人写的理解的,太菜了. 用sum1和sum2分别来表示覆盖数为1的区间长度和覆盖数为2的区间长度. 更新时即要更新sum1也要更新sum2: 区间如果被覆盖 sum1为实际区间长度,如果覆盖一次,sum2为左右子树的sum1和,覆盖两次就为实际区间长度. 没有被覆盖就直接等于左右子树的和. #include <algorithm> #include <iostream