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

这题写了很久很久
有点难受 现在还是有点迷糊
 #include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
using namespace std;
typedef long long LL;
const int maxn = 5e4 + ;
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("*******");
struct LINE {
int x, y1, y2, flag;
} line[maxn];
int cmp(LINE a, LINE b) {
if (a.x == b.x) return a.flag > b.flag;
return a.x < b.x;
}
struct node {
int l, r, line, cover;
int m, lbd, rbd;
} tree[maxn << ];
int y[maxn];
void build(int l, int r, int rt) {
tree[rt].l = l, tree[rt].r = r;
tree[rt].cover = tree[rt].m = tree[rt].line = ;
tree[rt].lbd = tree[rt].rbd = ;
if (r - l > ) {
int m = (l + r) >> ;
build(l, m, rtl);
build(m, r, rtr);
}
}
void update_line(int rt) {
if (tree[rt].cover > ) {
tree[rt].lbd = tree[rt].rbd = tree[rt].line = ;
} else if (tree[rt].r - tree[rt].l == ) {
tree[rt].lbd = tree[rt].rbd = tree[rt].line = ;
} else {
tree[rt].lbd = tree[rtl].lbd;
tree[rt].rbd = tree[rtr].rbd;
tree[rt].line = tree[rtl].line + tree[rtr].line - tree[rtl].rbd * tree[rtr].lbd;
}
}
void update_m(int rt) {
if (tree[rt].cover > ) tree[rt].m = y[tree[rt].r] - y[tree[rt].l];
else if (tree[rt].r - tree[rt].l == ) tree[rt].m = ;
else tree[rt].m = tree[rtl].m + tree[rtr].m; }
void add(int l, int r, int rt) {
if (y[tree[rt].l] >= l && y[tree[rt].r] <= r) tree[rt].cover++;
else if (tree[rt].r - tree[rt].l == ) return ;
else {
int m = (tree[rt].l + tree[rt].r) >> ;
if (r <= y[m]) add(l, r, rtl);
else if (l > y[m]) add(l, r, rtr);
else {
add(l, y[m], rtl);
add(y[m], r, rtr);
}
}
update_line(rt);
update_m(rt);
}
void del(int l, int r, int rt) {
if (y[tree[rt].l] >= l && y[tree[rt].r] <= r) tree[rt].cover--;
else if (tree[rt].r - tree[rt].l == ) return;
else {
int m = (tree[rt].l + tree[rt].r) >> ;
if (r <= y[m]) del(l, r, rtl);
else if (l > y[m]) del(l, r, rtr);
else {
del(l, y[m], rtl);
del(y[m], r, rtr);
}
}
update_line(rt);
update_m(rt);
}
int main() {
int n, cnt = ;
scanf("%d", &n);
for (int i = ; i < n ; i++) {
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
line[cnt].x = x1;
line[cnt].y1 = y1;
line[cnt].y2 = y2;
line[cnt].flag = ;
y[cnt++] = y1;
line[cnt].x = x2;
line[cnt].y1 = y1;
line[cnt].y2 = y2;
line[cnt].flag = ;
y[cnt++] = y2;
}
sort(y, y + cnt);
sort(line, line + cnt, cmp);
int len = unique(y, y + cnt) - y;
build(, len - , );
int ans = , now_m = , now_line = ;
for (int i = ; i < cnt ; i++) {
if (line[i].flag) add(line[i].y1, line[i].y2, );
else del(line[i].y1, line[i].y2, );
if (i >= ) ans += * now_line * (line[i].x - line[i - ].x);
ans += abs(tree[].m - now_m);
now_m = tree[].m;
now_line = tree[].line;
}
printf("%d\n", ans);
return ;
}

Picture POJ - 1177 (线段树-扫描线)的更多相关文章

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

    参考  https://www.cnblogs.com/null00/archive/2012/04/22/2464876.html #include <stdio.h> #include ...

  2. POJ - 1177 线段树

    POJ - 1177 扫描线 这道题也算是一道扫描线的经典题目了. 只不过这道题是算周长,非常有意思的一道题.我们已经知道了,一般求面积并,是如何求的,现在我们要把扫描线进行改造一下,使得能算周长. ...

  3. POJ 3277 线段树+扫描线

    题意: 思路: 线段树求矩形面积的并...同 POJ 1151 //By SiriusRen #include <cstdio> #include <algorithm> us ...

  4. POJ 1151 线段树+扫描线

    题意:求矩形面积的并 思路: 注意是[l,mid][mid,r] 这是真正的线段了 就当扫描线模板使吧~ //By SiriusRen #include <cmath> #include ...

  5. POJ 1151 线段树+扫描线(计算矩形面积并)

    前一篇博客有了讲解就不再叙述了 #include<cstdio> #include<cstring> #include<cmath> #include<ios ...

  6. 51nod 1206 Picture 矩形周长求并 | 线段树 扫描线

    51nod 1206 Picture 矩形周长求并 | 线段树 扫描线 #include <cstdio> #include <cmath> #include <cstr ...

  7. 线段树 扫描线 L - Atlantis HDU - 1542 M - City Horizon POJ - 3277 N - Paint the Wall HDU - 1543

    学习博客推荐——线段树+扫描线(有关扫描线的理解) 我觉得要注意的几点 1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1] 2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个pu ...

  8. hdu 1828 Picture(线段树扫描线矩形周长并)

    线段树扫描线矩形周长并 #include <iostream> #include <cstdio> #include <algorithm> #include &l ...

  9. HDU 1828“Picture”(线段树+扫描线求矩形周长并)

    传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...

  10. hdu1828 Picture(线段树+扫描线+矩形周长)

    看这篇博客前可以看一下扫描线求面积:线段树扫描线(一.Atlantis HDU - 1542(覆盖面积) 二.覆盖的面积 HDU - 1255(重叠两次的面积))  解法一·:两次扫描线 如图我们可以 ...

随机推荐

  1. Linux系统负载查询

    查询Linux系统负载情况,一般需要了解三个方面的信息: 1.Linux系统配置.如Linux版本号.CPU.内存.网络.磁盘等: 2.收集系统负载信息的手段.常用的工具包有sysstat和procp ...

  2. 《机器学习实战》笔记——决策树(ID3)

    现在要介绍的是ID3决策树算法,只适用于标称型数据,不适用于数值型数据. 决策树学习算法最大的优点是,他可以自学习,在学习过程中,不需要使用者了解过多的背景知识.领域知识,只需要对训练实例进行较好的标 ...

  3. sql STUFF 分组

    ---将sql想关的数据放到一个字段里 select r.Region_Name, )) [text()] from City c2 inner join Region as r2 on c2.Reg ...

  4. mysql 导入 大sql文件

    任务:第一次用mysql,需要将一个1G左右的sql文件导入: 步骤:1:安装mysql-installer-community-5.7.20.0.msi 64位安装包 2:命令行登录:  mysql ...

  5. 十一:Centralized Cache Management in HDFS 集中缓存管理

    集中的HDFS缓存管理,该机制可以让用户缓存特定的hdfs路径,这些块缓存在堆外内存中.namenode指导datanode完成这个工作. Centralized cache management i ...

  6. [C++] Variables and Basic Types

    Getting Started compile C++ program source $ g++ -o prog grog1.cc run C++ program $ ./prog The libra ...

  7. M2迭代分数分配

    M2中仍然依据每个成员的工作量,贡献度分配相应得分. 成员 得分 申开亮 25 王皓南 24 许晋 21 黄玉冰 20 王宇杰 18 吴润凡 17 巴丹益昔 15

  8. Java 抽象类和Final关键字

    抽象类 用abstract关键字来修饰一个类时,这个类叫抽象类: 用abstract关键字来修饰一个方法时,该方法叫做抽象方法. 含有抽象方法的类必须被定义而为抽象类,抽象类必须被继承,抽象方法必须被 ...

  9. 内部网关协议RIP 路由选择算法(距离向量)

    RIP是一种基于距离向量的路由选择协议 RIP的距离就是指的跳数,没经过一个路由,就是一跳,RIP允许一跳路径最多经过15个路由器,所以16个的话就相当于不可以到达了 RIP协议的特点: 1:仅和相邻 ...

  10. ajax的一些实用技巧

    1.尽量优先采用ajax获取html文件,然后再操作dom把数据填充到里面 在实际项目中,如果前端开发人员没有把页面给切分开,那么有如下两种办法可供选择:其一是,在各种点击事件中,用js去拼接并在拼接 ...