http://acm.hdu.edu.cn/showproblem.php?pid=1828

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Problem Description

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.
Please process to the end of file.

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

-
-
-
-

Sample Output


题意:

有多个矩形,矩形的两边平行于坐标轴,这些矩形之间可能存在相互覆盖,求周长。

思路:
记录每个矩形的两条竖边(x1,y1,y2)和(x2,y1,y2),将所有的竖边按照x从小到大排序,然后一条一条竖边开始计算周长,那么以竖边所在的垂直于x轴的直线即是扫描线。
每次移动到一条新的竖边的时候,我们需要计算所在竖边扫描线上有用边长(即当前竖边的有用部分,可能当前的竖边被覆盖部分),以及加上当前扫描线与上一条扫描线之前的横边长 * 横边条数,
一直计算到最后一条竖边,即是完整周长了。
 

用一次扫描线,离散y坐标,按x从左到右扫描,统计每次总和的更改值,这样可以得到所有纵向边的和,对于横向边,可以用(Line[i].x - Line[i-1].x)*SegTree[1].num*2.前面的(Line[i].x - Line[i-1].x)相邻的两条线

段的x坐标的差,SegTree[1].num代表此时在线段树中一共有几条线段,每一条线段,就会增加这条线段的两个端点带来的横边。所以只要统计到当时有多少段覆盖的边,就可以得到那一段的横向的增加值

统计某一时刻有多少线段覆盖,可以用lf , rf记录这一个节点的两个端点是不是已经覆盖,如果覆盖值为1,那么这一段的num就是1,合并两个节点的时候,父节点的num等于左右子节点的num和,如果左节点

的rf与右节点的lf都是1,那么父节点的num值减去1。最后得到统计整个线段是由几个线段组成。

代码如下:

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const int maxn=1e5+;
using namespace std; const int N=;
struct Line_node
{
int x;//横坐标
int y1,y2;//矩形纵向线段的左右端点
int flag;//标记是入边还是出边
bool operator < (const Line_node &s)
{
if(x==s.x)
return flag>s.flag;
else
return x<s.x;
}
}Line[N*]; struct SegTree_node
{
int l;
int r;
bool lf,rf;//左右边界点是否被覆盖;
int cover_len;
int cover_num;
int num;//矩形数目
}SegTree[maxn<<]; vector<int> vt; void Build(int l,int r,int rt)
{
SegTree[rt].l=l;
SegTree[rt].r=r;
SegTree[rt].cover_len=;
SegTree[rt].cover_num=;
SegTree[rt].num=;
SegTree[rt].lf=SegTree[rt].rf=false;
if(l+==r)
return ;
int mid=(l+r)>>;
Build(l,mid,rt<<);
Build(mid,r,rt<<|);
} void PushUp(int rt)
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(SegTree[rt].cover_num>)
{
SegTree[rt].cover_len=vt[r]-vt[l];
SegTree[rt].lf=SegTree[rt].rf=true;
SegTree[rt].num=;
return ;
}
// if(l+1==r)
// {
// SegTree[rt].cover_len=0;
// SegTree[rt].lf=SegTree[rt].rf=false;
// SegTree[rt].num=0;
// return ;
// }
SegTree[rt].cover_len=SegTree[rt<<].cover_len+SegTree[rt<<|].cover_len;
SegTree[rt].num=SegTree[rt<<].num+SegTree[rt<<|].num-(SegTree[rt<<].rf & SegTree[rt<<|].lf);//&按位与
SegTree[rt].lf=SegTree[rt<<].lf;
SegTree[rt].rf=SegTree[rt<<|].rf;
} void Update(Line_node t,int rt)
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(t.y1<=vt[l]&&t.y2>=vt[r])
{
SegTree[rt].cover_num+=t.flag;
PushUp(rt);
return ;
}
int mid=(l+r)>>;
if(t.y1<vt[mid])
Update(t,rt<<);
if(t.y2>vt[mid])
Update(t,rt<<|);
PushUp(rt);
} int main()
{
int n;
while (~scanf("%d",&n))
{
vt.clear();
for(int i=;i<n;i++)
{
int x1,x2,y1,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
Line[i*].x=x1;
Line[i*].y1=y1;
Line[i*].y2=y2;
Line[i*].flag=; Line[i*+].x=x2;
Line[i*+].y1=y1;
Line[i*+].y2=y2;
Line[i*+].flag=-;
vt.push_back(y1);
vt.push_back(y2);
}
sort(Line,Line+*n);
//y坐标离散化
sort(vt.begin(),vt.end());
int num=unique(vt.begin(),vt.end())-vt.begin();//去重并求出离散完的个数
Build(,num-,);
int ans=;//存累计面积
int prelen=;//前一个L值,刚开始是0
for(int i=;i<n*;i++)
{
if(i>)
{//SegTree[1].num代表目前线分成了几段,每段两个点,每个点一条横变
ans+=SegTree[].num**(Line[i].x-Line[i-].x);//先加横边
}
Update(Line[i],);//更新线段树中维护的线
ans+=abs(SegTree[].cover_len-prelen);//再加维护的线长度的变化值
prelen=SegTree[].cover_len;
}
printf("%d\n",ans);
}
return ;
}

HDU-1828 Picture(扫描线 求矩形并的周长)的更多相关文章

  1. 51nod 1206 && hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)

    1206 Picture  题目来源: IOI 1998 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  关注 给出平面上的N个矩形(矩形的边平行于X轴 ...

  2. poj 1177 --- Picture(线段树+扫描线 求矩形并的周长)

    题目链接 Description A number of rectangular posters, photographs and other pictures of the same shape a ...

  3. hdu 1828 Picture 切割线求周长

    Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  4. hdu1828 线段树扫描线求矩形面积的周长

    题意:       给你n个矩形,问你这n个矩形所围成的图形的周长是多少. 思路:       线段树的扫描线简单应用,这个题目我用的方法比较笨,就是扫描两次,上下扫描,求出多边形的上下边长和,然后同 ...

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

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

  6. (中等) HDU 1828 Picture,扫描线。

    Problem Description A number of rectangular posters, photographs and other pictures of the same shap ...

  7. HDU 1828 Picture(长方形的周长和)

    HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4 ...

  8. HDU 1828 Picture(线段树扫描线求周长)

    Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  9. hdu 1542 扫描线求矩形面积的并

    很久没做线段树了 求矩形面积的并分析:1.矩形比较多,坐标也很大,所以横坐标需要离散化(纵坐标不需要),熟悉离散化后这个步骤不难,所以这里不详细讲解了,不明白的还请百度2.重点:扫描线法:假想有一条扫 ...

随机推荐

  1. 微服务基础——厉害了!API网关

    微服务刚刚诞生的时候,人们将服务进行拆分,实现服务之间的松耦合,并且每个服务有专门的团队维护,然后客户端直接和各个子服务进行交互.比如,订单,商品,会员服务. 那么这种客户端直接和后端服务交互的方式会 ...

  2. 201771010123汪慧和《面向对象程序设计Java》第十八周实验总结

    一.总复习纲要 1. Java语言特点与开发环境配置(第1章.第2章) 2. Java基本程序结构(第3章) 3. Java面向对象程序结构(第4章.第5章.第6章) 4. 类.类间关系.类图 5. ...

  3. 洛谷 P5664 Emiya 家今天的饭(84分)

    题目传送门 解题思路: 对于每一个列c,f[i][j][k]表示到第i行,第c列选了j个,其它列一共选了k个,然后我们读题意发现只要j>k,那就一定是不合法的,然后统计所有方案,减去所有不合法方 ...

  4. .NET httpClient Post请求,GET请求方法

    1.后端是WebAPI,POST请求,修饰符是[FromBody]的字符串,[FromBody]修饰的时候数据是来自body部分,而不是来自url部分,所以后端取值会自动映射出数据,比如后端是这样的, ...

  5. Leetcode第1题:两数之和

    给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的 两个 整数.你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元素.示例:给定 nums ...

  6. Thread--对象锁猜想

    堆内存地址未发生变化: 对象堆内存地址没发生变化的情况下,即值是否与变仍然是同一把锁. 堆内存地址变化: 在线程尝试进入过同步代码时复制当前对象锁副本. 在复制对象锁副本之后改变对象指向不影响对象锁, ...

  7. win10设置开机以及开机无密码验证

    1.开机自启动 将程序的exe的快捷方式放入下列文件夹中 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp 2.开机无登录验证 ...

  8. Linux-异步IO

    1.何为异步IO (1).几乎可以这么认为:异步IO就是操作系统用软件实现的一套中断响应系统. (2).异步IO的工作方法:我们当前进程注册一个异步IO事件(使用signal注册一个信号SIGIO的处 ...

  9. 当初希望自己是如何投入这个专业的学习的?曾经做过什么准备,或者立下过什么FLAG吗?

    学习好累,打游戏好爽  我不爱学习 认真勤勉投入学习 精心准备,刻苦学习 我的flag   作为大学生,需要了解今后职场社会,对职业方向有了进一步的认识.社会对于人才的要求在某些方面都是不谋而合的,比 ...

  10. uploadify ASP.net 使用笔记

    <script type="text/javascript" src="jquery.uploadify.min.js"></script & ...