POJ 1151 Atlantis (扫描线+线段树)
题目链接:http://poj.org/problem?id=1151
题意是平面上给你n个矩形,让你求矩形的面积并。
首先学一下什么是扫描线:http://www.cnblogs.com/scau20110726/archive/2013/04/12/3016765.html
这是别人的blog,写的挺好的。然后明白扫描线之后呢,接下来就很简单了,只需要一次一次求面积然后累加就好了。这题离散化之后,数据的范围更小了(因为n只有100),单点更新就行了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 using namespace std; 7 const int MAXN = 2e2 + 5; 8 struct data { 9 double x1 , x2; 10 double y; 11 int xx1 , xx2 , flag; //flag: 1表示加 -1表示减 xx1 xx2是离散化之后的值 12 bool operator <(const data& cmp) const { 13 return y < cmp.y; 14 } 15 }edge[MAXN << 2]; 16 struct segtree { 17 int l , r , lazy; //lazy表示累加的次数 18 double val; //val表示长度 19 }T[MAXN << 2]; 20 double x[MAXN]; 21 map <double , int> mp; 22 23 double min(double a , double b) { 24 return a > b ? b : a; 25 } 26 27 double max(double a , double b) { 28 return a > b ? a : b; 29 } 30 31 void init(int p , int l , int r) { 32 int mid = (l + r) >> 1; 33 T[p].l = l , T[p].r = r , T[p].val = T[p].lazy = 0; 34 if(r - l == 1) { 35 return ; 36 } 37 init(p << 1 , l , mid); 38 init((p << 1)|1 , mid , r); 39 } 40 41 void updata(int p , int l , int r , int val) { 42 int mid = (T[p].l + T[p].r) >> 1; 43 if(T[p].r - T[p].l == 1) { 44 if(val == -1) { 45 T[p].lazy--; 46 T[p].val = T[p].lazy ? (x[T[p].r] - x[T[p].l]) : 0; 47 } 48 else { 49 T[p].lazy++; 50 T[p].val = (x[T[p].r] - x[T[p].l]); 51 } 52 return ; 53 } 54 if(r <= mid) { 55 updata(p << 1 , l , r , val); 56 } 57 else if(l >= mid) { 58 updata((p << 1)|1 , l , r , val); 59 } 60 else { 61 updata(p << 1 , l , mid , val); 62 updata((p << 1)|1 , mid , r , val); 63 } 64 T[p].val = T[p << 1].val + T[(p << 1)|1].val; 65 } 66 67 int main() 68 { 69 int n , ca = 1; 70 double x1 , x2 , y1 , y2; 71 while(~scanf("%d" , &n) && n) { 72 int cont = 0; 73 mp.clear(); 74 for(int i = 0 ; i < n ; i++) { 75 scanf("%lf %lf %lf %lf" , &x1 , &y1 , &x2 , &y2); 76 edge[i * 2].x1 = min(x1 , x2) , edge[i * 2].x2 = max(x1 , x2); 77 edge[i * 2].y = min(y1 , y2); 78 edge[i * 2].flag = 1; 79 edge[i * 2 + 1].x1 = edge[i * 2].x1 , edge[i * 2 + 1].x2 = edge[i * 2].x2; 80 edge[i * 2 + 1].y = max(y1 , y2); 81 edge[i * 2 + 1].flag = -1; 82 if(!mp[x1]) { 83 x[++cont] = x1; 84 mp[x1]++; 85 } 86 if(!mp[x2]) { 87 x[++cont] = x2; 88 mp[x2]++; 89 } 90 } 91 sort(edge , edge + n * 2); 92 sort(x + 1 , x + cont + 1); 93 for(int i = 0 ; i < n * 2 ; i++) { 94 int pos = (lower_bound(x + 1 , x + cont + 1 , edge[i].x1) - x); 95 edge[i].xx1 = pos; 96 pos = (lower_bound(x + 1 , x + cont + 1 , edge[i].x2) - x); 97 edge[i].xx2 = pos; 98 } 99 init(1 , 1 , cont); 100 double res = 0; 101 updata(1 , edge[0].xx1 , edge[0].xx2 , edge[0].flag); 102 for(int i = 1 ; i < n * 2 ; i++) { 103 res += T[1].val * (edge[i].y - edge[i - 1].y); 104 updata(1 , edge[i].xx1 , edge[i].xx2 , edge[i].flag); 105 } 106 printf("Test case #%d\n" , ca++); 107 printf("Total explored area: %.2f\n\n" , res); 108 } 109 }