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 }

 

posted @ 2016-04-25 20:18  Recoder  阅读(202)  评论(0编辑  收藏  举报