HDU-1828 Picture(扫描线 求矩形并的周长)
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
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
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
Sample Input
-
-
-
-
Sample Output
题意:
有多个矩形,矩形的两边平行于坐标轴,这些矩形之间可能存在相互覆盖,求周长。
用一次扫描线,离散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(扫描线 求矩形并的周长)的更多相关文章
- 51nod 1206 && hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)
1206 Picture 题目来源: IOI 1998 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 给出平面上的N个矩形(矩形的边平行于X轴 ...
- poj 1177 --- Picture(线段树+扫描线 求矩形并的周长)
题目链接 Description A number of rectangular posters, photographs and other pictures of the same shape a ...
- hdu 1828 Picture 切割线求周长
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- hdu1828 线段树扫描线求矩形面积的周长
题意: 给你n个矩形,问你这n个矩形所围成的图形的周长是多少. 思路: 线段树的扫描线简单应用,这个题目我用的方法比较笨,就是扫描两次,上下扫描,求出多边形的上下边长和,然后同 ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- (中等) HDU 1828 Picture,扫描线。
Problem Description A number of rectangular posters, photographs and other pictures of the same shap ...
- HDU 1828 Picture(长方形的周长和)
HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4 ...
- HDU 1828 Picture(线段树扫描线求周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- hdu 1542 扫描线求矩形面积的并
很久没做线段树了 求矩形面积的并分析:1.矩形比较多,坐标也很大,所以横坐标需要离散化(纵坐标不需要),熟悉离散化后这个步骤不难,所以这里不详细讲解了,不明白的还请百度2.重点:扫描线法:假想有一条扫 ...
随机推荐
- linux文件编辑VI命令详解
vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...
- git使用散记
1.从远程clone一个项目 git clone ‘项目地址’ //clone项目地 git checkout -b dev origin/dev //远程已有dev分支,新建本地dev分支与远程相对 ...
- django-替代为自定义的User model
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model Subs ...
- bestphp's revenge
0x00 知识点 1利用PHP原生类来构造POP链 本题没有可以利用的类,没有可以利用的类就找不到POP链所以只能考虑PHP原生类 我们先来解释一下什么是POP链 POP:面向属性编程 在二进制利用时 ...
- 建立更可靠的OOP程序-类和成员的访问控制
1. public 成员(公共成员) (1)使用this 关键字的类的成员允许在任何地方被访问. (2)使用 prototype 定义的属性和方法都是公共成员. 这些属性和方法可以在外面任何地方被访问 ...
- 计算机网络(1): http原理和uuid
http 的请求报文和响应报文格式 请求报文有哪些方法 一个典型的http报文 状态码有哪几种 以及短语是用来解释状态码的 接口测试中,需要使用到UUID,用来生成唯一ID. 1.什么是UUID UU ...
- Navicat mysql 数据库备份和使用,备份以后是nb3文件
通过Navicat进行Mysql数据库自动备份与还原 Mysql数据库自动备份流程 Navicat版本为:Navicat 12.0.26 例:test为用于测试自动备份的数据库,里面有表t_per ...
- Runtime之方法交换
在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写.和借助类别重名方法暴力抢先之外,还有就是方法交换 方法交换的原理:在OC中调用一个方法其实是向一个对象发送消息,查找消息的唯一 ...
- python对数组缺失值进行填充
1. 两个常用的函数 1.1 np.nonzero() np.nonzero()函数返回数组中不为False(0)的元素对应的索引 a = np.array([1,2,0,3,1,0]) print( ...
- Linux-异步IO
1.何为异步IO (1).几乎可以这么认为:异步IO就是操作系统用软件实现的一套中断响应系统. (2).异步IO的工作方法:我们当前进程注册一个异步IO事件(使用signal注册一个信号SIGIO的处 ...