HDU1542 Atlantis —— 求矩形面积并 线段树 + 扫描线 + 离散化
题目链接:https://vjudge.net/problem/HDU-1542
InputThe input file 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.OutputFor 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
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const LL LNF = 2e18; 17 const int MAXN = 1e5+10; 18 19 struct line 20 { 21 double le, ri, h; 22 int id; 23 bool operator<(const line &a)const{ 24 return h<a.h; 25 } 26 }Line[MAXN]; 27 28 //X用于离散化横坐标,times为此区间被覆盖的次数,sum为此区间被覆盖的长度 29 double X[MAXN], times[MAXN<<2], sum[MAXN<<2]; 30 31 void push_up(int u, int l, int r) 32 { 33 if(times[u]>0) //该区间被覆盖,则覆盖长度为区间长度 34 sum[u] = X[r] - X[l]; 35 else //该区间没有被覆盖,如果为单位区间,则覆盖长度为0,否则为两个子区间的覆盖长度之和。 36 sum[u] = (l+1==r)?0:sum[u*2]+sum[u*2+1]; 37 } 38 39 //此种线段树的操作对象为连续型,即最小的元素为长度为1的区间[l,r],其中l和r只代表端点(r-l>=1),用于确定 40 //区间的位置和长度,l和r本身没有特别的含义。而以往做的什么单点更新之类的,都属于离散型,在l处和r处是有含义的 41 void add(int u, int l, int r, int x, int y, int v) 42 { 43 if(x<=l && r<=y) 44 { 45 times[u] += v; 46 push_up(u, l, r); 47 return; 48 } 49 50 int mid = (l+r)>>1; 51 if(x<=mid-1) add(u*2, l, mid, x, y, v); 52 if(y>=mid+1) add(u*2+1, mid, r, x, y, v); 53 push_up(u, l, r); 54 } 55 56 int main() 57 { 58 int n, kase = 0; 59 while(scanf("%d", &n) && n) 60 { 61 for(int i = 1; i<=n; i++) 62 { 63 double x1, y1, x2, y2; 64 scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); 65 Line[i].le = Line[i+n].le = x1; 66 Line[i].ri = Line[i+n].ri = x2; 67 Line[i].h = y1; Line[i+n].h = y2; 68 Line[i].id = 1; Line[i+n].id = -1; 69 X[i] = x1; X[i+n] = x2; 70 } 71 72 sort(Line+1, Line+1+2*n); 73 sort(X+1, X+1+2*n); 74 int m = unique(X+1, X+1+2*n) - (X+1); //去重 75 76 memset(sum, 0, sizeof(sum)); 77 memset(times, 0, sizeof(times)); 78 79 double ans = 0; 80 for(int i = 1; i<=2*n-1; i++) 81 { 82 int l = upper_bound(X+1, X+1+m, Line[i].le) - (X+1); 83 int r = upper_bound(X+1, X+1+m, Line[i].ri) - (X+1); 84 add(1, 1, m, l, r, Line[i].id); 85 ans += sum[1]* (Line[i+1].h-Line[i].h); 86 } 87 printf("Test case #%d\n", ++kase); 88 printf("Total explored area: %.2f\n\n", ans); 89 } 90 }