Hdu 1255

题目链接

覆盖的面积

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3545    Accepted Submission(s): 1739


Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

Hdu 1255

 

Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

注意:本题的输入数据较多,推荐使用scanf读入数据.

 

Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.

 

Sample Input
2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1

 

Sample Output
7.63 0.00
计算被两个及以上矩形覆盖的面积和。
此种类型题目有两种做法。
第一种效率较低:
Accepted Code:
  1 /*************************************************************************

  2     > File Name: G.cpp

  3     > Author: Stomach_ache

  4     > Mail: [email protected]

  5     > Created Time: 2014年07月26日 星期六 19时05分05秒

  6     > Propose: hdu 1542

  7  ************************************************************************/

  8 #include <cmath>

  9 #include <string>

 10 #include <cstdio>

 11 #include <fstream>

 12 #include <cstring>

 13 #include <iostream>

 14 #include <algorithm>

 15 using namespace std;

 16 

 17 const int maxn = 1100;

 18 struct Line {

 19       double x, y1, y2;

 20     int cover;

 21     friend bool operator < (Line a, Line b) {

 22           return a.x < b.x;

 23     }

 24 }line[maxn*2 + 5];

 25 

 26 struct node {

 27       double x, y1, y2;

 28     int cover, flag;

 29 }Tree[maxn*1000];

 30 int n;

 31 double y[maxn*2];

 32 

 33 void build(int root, int L, int R) {

 34       Tree[root].x = -1;

 35       Tree[root].cover = 0;

 36     Tree[root].y1 = y[L];

 37     Tree[root].y2 = y[R];

 38     Tree[root].flag = 0;

 39       if (R - L == 1) {

 40           Tree[root].flag = 1;

 41         return ;

 42     }

 43     int M = (L + R) / 2;

 44     build(root * 2, L, M);

 45     build(root * 2 + 1, M, R);

 46 }

 47 

 48 double insert(int root, Line &ll) {

 49       if (Tree[root].y1 >= ll.y2 || Tree[root].y2 <= ll.y1) {

 50           return 0.0;

 51     }

 52     if (Tree[root].flag) {

 53           if (Tree[root].cover > 1) {

 54             double ans = (ll.x - Tree[root].x) * (Tree[root].y2 - Tree[root].y1);

 55             Tree[root].x = ll.x;

 56               Tree[root].cover += ll.cover;

 57             return ans;

 58         } else {

 59               Tree[root].cover += ll.cover;

 60             Tree[root].x = ll.x;

 61             return 0.0;

 62         }

 63     }

 64     double ans1 = insert(root * 2, ll);

 65     double ans2 = insert(root * 2 + 1, ll);

 66     return ans1 + ans2;

 67 }

 68 

 69 int main(void) {

 70 #ifndef ONLINE_JUDGE

 71       freopen("in.txt", "r", stdin);

 72 #endif

 73       int cas;

 74     scanf("%d", &cas);

 75       while (cas--) {

 76         scanf("%d", &n); 

 77           int cnt = 0;

 78           for (int i = 0; i < n; i++) {

 79              double xx, yy, xxx, yyy;

 80             scanf("%lf %lf %lf %lf", &xx, &yy, &xxx, &yyy);

 81             y[++cnt] = yy;

 82             line[cnt].x = xx; line[cnt].y1 = yy; line[cnt].y2 = yyy;

 83             line[cnt].cover = 1;

 84             y[++cnt] = yyy;

 85             line[cnt].x = xxx; line[cnt].y1 = yy; line[cnt].y2 = yyy;

 86             line[cnt].cover = -1;

 87         }

 88         sort(y + 1, y + cnt + 1);

 89         int len = 1;

 90         for (int i = 2; i <= cnt; i++) {

 91               if (y[i] != y[len]) {

 92                   y[++len] = y[i];

 93             }

 94         }

 95         sort(line + 1, line + cnt + 1);

 96         build(1, 1, len);

 97         double ans = 0.0;

 98         for (int i = 1; i <= cnt; i++) {

 99               ans += insert(1, line[i]);

100         }

101         printf("%.2f\n", ans);

102     }

103 

104     return 0;

105 }

第二种做法效率较高。

Accepted Code:
 1 /*************************************************************************  2  > File Name: G.cpp  3  > Author: Stomach_ache  4  > Mail: [email protected]  5  > Created Time: 2014年07月26日 星期六 19时05分05秒  6  > Propose: hdu  7  ************************************************************************/

 8 #include <map>

 9 #include <cmath>

 10 #include <string>

 11 #include <cstdio>

 12 #include <vector>

 13 #include <fstream>

 14 #include <cstring>

 15 #include <iostream>

 16 #include <algorithm>

 17 using namespace std;  18 

 19 const int maxn = 1100;  20 //保存每条线段的信息

 21 struct Line {  22       double x, y1, y2;  23     //矩形的左边或者右边

 24     int flag;  25     friend bool operator < (Line a, Line b) {  26           return a.x < b.x;  27  }  28 }line[maxn*2 + 5];  29 

 30 //线段树结点信息

 31 struct node {  32       int l, r;  33     //线段被覆盖的次数

 34     int cover;  35     //len为被覆盖一次的长度,len2为被覆盖两次的长度

 36     double len, len2;  37 }Tree[maxn*40];  38 int n;  39 //保存所有y轴坐标

 40 double y[maxn*2];  41 //离散化使用

 42 vector<double> xs;  43 

 44 void build(int root, int L, int R) {  45       Tree[root].l = L;  46     Tree[root].r = R;  47       Tree[root].len = 0.0;  48     Tree[root].len2 = 0.0;  49       Tree[root].cover = 0;  50       if (R - L == 1) {  51         return ;  52  }  53     int M = (L + R) / 2;  54     build(root * 2, L, M);  55     build(root * 2 + 1, M, R);  56 }  57 

 58 void pushup(int root) {  59       //被覆盖两次以上

 60     if (Tree[root].cover > 1) {  61           Tree[root].len = 0;  62           Tree[root].len2 = xs[Tree[root].r-1] - xs[Tree[root].l-1];  63     } else if (Tree[root].cover == 1) { //被覆盖一次

 64         Tree[root].len2 = Tree[root*2].len + Tree[root*2+1].len  65                            +Tree[root*2].len2 + Tree[root*2+1].len2;  66           Tree[root].len = xs[Tree[root].r-1] - xs[Tree[root].l-1]  67                            - Tree[root].len2;  68     } else { //没有被覆盖

 69          if (Tree[root].l + 1 == Tree[root].r)  70             Tree[root].len = Tree[root].len2 = 0.0;  71         else {  72             Tree[root].len = Tree[root*2].len + Tree[root*2+1].len;  73             Tree[root].len2 = Tree[root*2].len2 + Tree[root*2+1].len2;  74  }  75  }  76 }  77 

 78 void update(int root, int L, int R, int flag) {  79       //不在当前区间内

 80       if (Tree[root].l >= R || Tree[root].r <= L)  81           return ;  82     //包含在当前区间内

 83       if (Tree[root].l >= L && Tree[root].r <= R) {  84         Tree[root].cover += flag;  85  pushup(root);  86           return ;  87  }  88     int M = (Tree[root].l + Tree[root].r) / 2;  89     update(root*2, L, R, flag);  90     update(root*2+1, L, R, flag);  91  pushup(root);  92 }  93 

 94 //离散化

 95 int compress(int m) {  96  xs.clear();  97     for (int i = 1; i <= m; i++) xs.push_back(y[i]);  98  sort(xs.begin(), xs.end());  99  xs.erase(unique(xs.begin(), xs.end()), xs.end()); 100     return xs.size(); 101 } 102 

103 

104 int main(void) { 105 #ifndef ONLINE_JUDGE 106       freopen("in.txt", "r", stdin); 107 #endif

108       int cas; 109     scanf("%d", &cas); 110       while (cas--) { 111           scanf("%d", &n); 112           int cnt = 0; 113           for (int i = 0; i < n; i++) { 114              double xx, yy, xxx, yyy; 115             scanf("%lf %lf %lf %lf", &xx, &yy, &xxx, &yyy); 116             y[++cnt] = yy; 117             line[cnt].x = xx; line[cnt].y1 = yy; line[cnt].y2 = yyy; 118             line[cnt].flag = 1; 119             y[++cnt] = yyy; 120             line[cnt].x = xxx; line[cnt].y1 = yy; line[cnt].y2 = yyy; 121             line[cnt].flag = -1; 122  } 123         int w = compress(cnt); 124         sort(line + 1, line + cnt + 1); 125         build(1, 1, cnt); 126         double ans = 0.0; 127         int l = find(xs.begin(), xs.end(), line[1].y1) - xs.begin() + 1; 128         int r = find(xs.begin(), xs.end(), line[1].y2) - xs.begin() + 1; 129         update(1, l, r, line[1].flag); 130         for (int i = 2; i <= cnt; i++) { 131               int l = find(xs.begin(), xs.end(), line[i].y1) - xs.begin() + 1; 132             int r = find(xs.begin(), xs.end(), line[i].y2) - xs.begin() + 1; 133             ans += (line[i].x - line[i-1].x) * Tree[1].len2; 134               update(1, l, r, line[i].flag); 135  } 136         printf("%.2f\n", ans); 137  } 138 

139     return 0; 140 }

 

你可能感兴趣的:(HDU)