Picture POJ - 1177

A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter.

Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1. 

The corresponding boundary is the whole set of line segments drawn in Figure 2. 

The vertices of all rectangles have integer coordinates.

Input

Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.

0 <= number of rectangles < 5000 
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

Output

Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.

Sample Input

7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16

Sample Output

228

分析:扫描线,横线的周长是每次扫描上一次的覆盖长度与这一次差的绝对值,竖线的周长是本次扫描的高度*2*线段数代码:
  1 #include <iostream>
  2 #include <algorithm>
  3 using namespace std;
  4 const int inf = 0x3f3f3f3f;
  5 const int maxn = 2e4 + 10;
  6 struct edge
  7 {
  8     int l, r;
  9     int h;
 10     int pos;
 11     bool operator < (const edge& a)const
 12     {
 13         return h < a.h;
 14     }
 15     edge(int a = 0, int b = 0, int c = 0, int d = 0) : l(a), r(b), h(c), pos(d){}
 16 }e[5010 << 1];
 17
 18 struct node
 19 {
 20     int l, r;
 21     int flag;
 22     int len;
 23     int num;
 24     int ll, rr;
 25 }t[maxn << 2];
 26
 27 bool cmp(edge &a, edge &b)
 28 {
 29     return a < b;
 30 }
 31
 32 void pushup(int tar)
 33 {
 34     if (t[tar].flag)
 35     {
 36         t[tar].len = t[tar].r - t[tar].l + 1;
 37         t[tar].ll = t[tar].rr = 1;
 38         t[tar].num = 1;
 39     }
 40     else if (t[tar].l == t[tar].r)
 41         t[tar].len = t[tar].ll = t[tar].rr = t[tar].num = 0;
 42     else
 43     {
 44         t[tar].len = t[tar << 1].len + t[tar << 1 | 1].len;
 45         t[tar].num = t[tar << 1].num + t[tar << 1 | 1].num - (t[tar << 1].rr & t[tar << 1 | 1].ll);
 46         t[tar].ll = t[tar << 1].ll, t[tar].rr = t[tar << 1 | 1].rr;
 47     }
 48 }
 49
 50 void build(int l, int r, int tar)
 51 {
 52     t[tar].l = l, t[tar].r = r, t[tar].flag = 0;
 53     t[tar].len = t[tar].num = 0;
 54     t[tar].rr = t[tar].ll = 0;
 55     if (l == r) return;
 56     int mid = (l + r) >> 1;
 57     build(l, mid, tar << 1);
 58     build(mid + 1, r, tar << 1 | 1);
 59 }
 60
 61 void update(int l, int r, int tar, int v)
 62 {
 63     if (l == t[tar].l && r == t[tar].r)
 64     {
 65         t[tar].flag += v;
 66         pushup(tar);
 67         return;
 68     }
 69     int mid = (t[tar].l + t[tar].r) >> 1;
 70     if (r <= mid) update(l, r, tar << 1, v);
 71     else if (l > mid) update(l, r, tar << 1 | 1, v);
 72     else update(l, mid, tar << 1, v), update(mid + 1, r, tar << 1 | 1, v);
 73     pushup(tar);
 74 }
 75
 76 int main()
 77 {
 78     int n; cin >> n;
 79     int tot = 0;
 80     int x1, y1, x2, y2;
 81     int max1, max2;
 82
 83     max1 = inf, max2 = -inf;
 84     for (int i = 1; i <= n; i++)
 85     {
 86         scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
 87         max1 = min(max1, min(x1, x2));
 88         max2 = max(max2, max(x1, x2));
 89         e[++tot] = edge(x1, x2, y1, -1);
 90         e[++tot] = edge(x1, x2, y2, 1);
 91     }
 92     sort(e + 1, e + 1 + tot, cmp);
 93     build(max1, max2 - 1, 1);
 94
 95     int res = 0;
 96     int last = 0;
 97
 98     for (int i = 1; i <= tot; i++)
 99     {
100         update(e[i].l, e[i].r - 1, 1, e[i].pos);
101         res += abs(t[1].len - last);
102         res += (e[i + 1].h - e[i].h) * 2 * t[1].num;
103         last = t[1].len;
104     }
105     cout << res << endl;
106 }


原文地址:https://www.cnblogs.com/liuwenhan/p/11419989.html

时间: 2024-10-14 04:27:58

Picture POJ - 1177的相关文章

hdu1828 (Picture) &amp;poj 1177( Picture)&amp;sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)

题目地址:hdu1828 (Picture)  & poj 1177( Picture) & sdibt 2390(5.5.1 Picture 矩形周长) 题目大意: 给你N个矩形,求出N个矩形构成的周长. 解题思路: 线段数+扫描线. 推荐博客: POJ1177 Picture(线段树求轮廓周长) POJ 1177 Picture (线段树+离散化+扫描线) 详解 注意事项: 该题在求面积的基础上有了升级,多写了一个被调需要求出投影与Y轴有几段,不然样例会少算20,就是给出图形中间的小矩

N - Picture - poj 1177(扫描线求周长)

题意:求周长的,把矩形先进行融合后的周长,包括内周长 分析:刚看的时候感觉会跟棘手,让人无从下手,不过学过扫描线之后相信就很简单了吧(扫描线的模板- -),还是不说了,下面是一精确图,可以拿来调试数据 ***************************************************************************************************************** #include<stdio.h>#include<math.

Picture POJ - 1177(扫描线 + 线段树)

题意:求矩形并的面积.. 解析: 扫描线第一道题....自下而上扫描的... 如果不懂什么是扫描线戳我 #include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <q

Picture POJ - 1177 线段树+离散化+扫描线 求交叉图像周长

参考  https://www.cnblogs.com/null00/archive/2012/04/22/2464876.html #include <stdio.h> #include <algorithm> #define LEN 10000 using namespace std; struct Node { int left; int right; int count;//被覆盖次数 //所包含的区间数量,如三条[1,2],[2,3],[4,5]线段被覆盖,则line=2

POJ 1177 Picture(扫描线求周长)

与求面积并的差不多,但是这个与扫描的方向相同的情况不太好处理,如果扫描线离散化两次扫两遍其实也可以解决这个问题,但是这样无论在时间还是空间上稍微就有点浪费了啊.这里因为我是离散x坐标的所以对于平行于y轴的方向上的统计比较难统计.处理的方法是:标记区间左边的断点,和右边的断点,求出这个区间一共有多少个断点.就可以统计出平行于y轴的长度了.这里合并的时候需要判断右边的左区间和左边的右区间是否相同,如果相同的话,说明他们连接到了一起,要减去多加的. Picture Time Limit: 2000MS

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

poj 1177 Picture(扫描线+矩形周长并)

http://poj.org/problem?id=1177 求矩形的周长并,明确的一点是对于覆盖的边的长度忽略不计. 与求面积并类似,首先离散化,对矩形的每条横边从下往上扫描.扫描过程中要完成三个任务,更新相应的区间信息,求横边长,求竖边长. 节点信息: l,r:左右区间编号 cnt:表示该区间是否被完全覆盖.cnt > 0 表示完全覆盖,否则不完全覆盖. lp,rp:表示该区间的两个端点是否被覆盖,为1被覆盖,为0没被覆盖. num:该区间被覆盖的线段数目.例如区间[1,10],当更新[2,

poj 1177 Picture(线段树周长并)

题目链接:http://poj.org/problem?id=1177 题意:给你n个矩形问你重叠后外边缘总共多长. 周长并与面积并很像只不过是处理的时候是   增加的周长=abs(上一次的线段的长度-更新后线段的长度) 然后分别处理一下竖着的边和横着的边就好了即建两次树就好. 就是一道典型的周长并问题,可以拿来练练周长并的写法. #include <iostream> #include <cstring> #include <algorithm> #include &

POJ 1177 &amp; HDU 1828 Picture(扫描线 + 求周长)

题目链接: POJ:http://poj.org/problem?id=1177 HDU:http://acm.hdu.edu.cn/showproblem.php?pid=1828 几个不错的讲解: http://www.cnblogs.com/scau20110726/archive/2013/04/13/3018702.html http://blog.csdn.net/xingyeyongheng/article/details/8931410 Description A number