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

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

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 1255,布布扣,bubuko.com

时间: 2024-10-13 14:54:37

Hdu 1255的相关文章

扫描线三巨头 hdu1928&amp;&amp;hdu 1255 &amp;&amp; hdu 1542 [POJ 1151]

学习链接:http://blog.csdn.net/lwt36/article/details/48908031 学习扫描线主要学习的是一种扫描的思想,后期可以求解很多问题. 扫描线求矩形周长并 hdu 1928 Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4795    Accepted Submission(s):

hdu 1255 覆盖的面积(扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1255 一道挺简单的题,让我折腾了许久.主要卡在了更新节点后维护父亲节点上.后来思路明确了就很容易了. 节点信息: l,r:区间端点 cnt:区间被覆盖的次数,cnt = 0说明没有被完全覆盖. len1:区间被覆盖的长度 len2:区间至少被两条线段覆盖的长度. 只要找到父亲节点与子节点在len1,len2,cnt的关系就简单了. #include <stdio.h> #include <iostre

hdu 1255 覆盖的面积

http://acm.hdu.edu.cn/showproblem.php?pid=1255 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 100010 5 using namespace std; 6 7 int t,n; 8 double Y[maxn],X[maxn]; 9 struct point 10 { 11 double x; 12 double

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

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

hdu 1255 覆盖的面积(线段树&amp;扫描线&amp;重复面积)

覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3375    Accepted Submission(s): 1645 Problem Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数

HDU 1255 离散化+扫描线覆盖的面积

覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3571    Accepted Submission(s): 1753 Problem Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据

hdu 1255 覆盖的面积 线段树扫描线求重叠面积

稀里糊涂打完了没想到1A了,心情还是很舒畅的,c和c++的四舍五入还是四舍六入遇积进位遇偶舍,我感觉很混乱啊,这道题我输出的答案是7.62,也就是遇偶舍了,可是我就手动处理一下进位问题,发现0.005 系统自动进位0.01了,尼玛啊,我一下子就混乱了,不是遇偶舍么,0也是偶数啊,怎么就进位了呢.最后我就不手动处理进位问题了,直接0.2lf%,虽然我输出的结果是7.62,但是提交也过了 这道题和poj1151,hdu1542差不多,扫描线详细讲解http://blog.csdn.net/young

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化一下,数据大小就缩小了,那么之后只需要线段树单点更新就好了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <map> 5 #include <algor

hdu 1255(线段树 扫描线) 覆盖的面积

http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所有的横坐标和纵坐标排序 因为是从左到右扫描,那么横坐标应该离散化一下 当扫描线依次扫描的时候,依次扫描到的纵区间在线段树中查找,依据是上边还是下边记录,上边就是-1,下边就是+1, 如果某区间记录值为0的时候,代表没有被覆盖,为1的时候代表覆盖一次,为2代表覆盖两次(不会出现为负数的情况) 最后将依