HDU-1828-Picture(线段树)
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.
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.
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
228
思路:求纵向边要维护重叠次数大于0的纵向长度。用上一次的node[1].m减去当前的node[1].m的绝对值。求横向边要维护每一次更新之后须要加上去的边数。
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std; struct L{
int val;//1 左边。-1 右边
int x,y1,y2;
}l[10000]; struct N{
int l,r,n,m;//n记录节点相应的有效横向边数量,m记录纵向长度
int cnt;//重叠情况
bool lc,rc;
}node[40000]; int tempy[10000]; bool cmp(struct L a,struct L b)
{
if(a.x==b.x) return a.val>b.val; return a.x<b.x;
} void build(int idx,int s,int e)
{
node[idx].cnt=0;
node[idx].m=0;
node[idx].lc=node[idx].rc=0;
node[idx].l=tempy[s-1];
node[idx].r=tempy[e-1]; if(s+1!=e)
{
int mid=(s+e)>>1; build(idx<<1,s,mid);
build(idx<<1|1,mid,e);
}
} void len(int idx,int s,int e)
{
if(node[idx].cnt>0)
{
node[idx].m=node[idx].r-node[idx].l;
node[idx].n=2;//相应两条边
node[idx].lc=node[idx].rc=1;
}
else
{
if(s+1!=e)
{
int mid=(s+e)>>1; node[idx].m=node[idx<<1].m+node[idx<<1|1].m;
node[idx].n=node[idx<<1].n+node[idx<<1|1].n;
node[idx].lc=node[idx<<1].lc;
node[idx].rc=node[idx<<1|1].rc;
if(node[idx<<1].rc && node[idx<<1|1].lc) node[idx].n-=2;//假设左右儿子是连着的。就要减去多计算的两条边
}
else
{
node[idx].m=0;
node[idx].n=0;
node[idx].lc=node[idx].rc=0;
}
}
} void update(int idx,int s,int e,struct L line)
{
if(node[idx].l==line.y1 && node[idx].r==line.y2)
{
node[idx].cnt+=line.val;
len(idx,s,e);
return;
} if(s+1!=e)
{
int mid=(s+e)>>1; if(line.y2<=node[idx<<1].r) update(idx<<1,s,mid,line);
else if(line.y1>=node[idx<<1|1].l) update(idx<<1|1,mid,e,line);
else
{
int temp=line.y2; line.y2=node[idx<<1].r;
update(idx<<1,s,mid,line);
line.y2=temp; line.y1=node[idx<<1|1].l;
update(idx<<1|1,mid,e,line);
} } len(idx,s,e);
} int main()
{
int T,n,i,t;
int x1,x2,y1,y2; while(~scanf("%d",&n))
{
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2); tempy[i*2]=y1;
tempy[i*2+1]=y2; l[i*2].val=1;
l[i*2].x=x1;
l[i*2].y1=y1;
l[i*2].y2=y2; l[i*2+1].val=-1;
l[i*2+1].x=x2;
l[i*2+1].y1=y1;
l[i*2+1].y2=y2;
} sort(tempy,tempy+n*2);
sort(l,l+n*2,cmp); t=unique(tempy,tempy+n*2)-tempy;//去重 build(1,1,t); int ans=0,last=0; for(i=0;i<n*2;i++)
{
if(i) ans+=node[1].n*(l[i].x-l[i-1].x); update(1,1,t,l[i]); ans+=abs(node[1].m-last);
last=node[1].m;
} printf("%d\n",ans);
}
}
HDU-1828-Picture(线段树)的更多相关文章
- hdu 1828 Picture(线段树 || 普通hash标记)
http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others) Mem ...
- POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算
求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...
- HDU 1828 Picture (线段树+扫描线)(周长并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 给你n个矩形,让你求出总的周长. 类似面积并,面积并是扫描一次,周长并是扫描了两次,x轴一次,y ...
- hdu 1828 Picture(线段树轮廓线)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- HDU 1828 Picture (线段树:扫描线周长)
依然是扫描线,只不过是求所有矩形覆盖之后形成的图形的周长. 容易发现,扫描线中的某一条横边对答案的贡献. 其实就是 加上/去掉这条边之前的答案 和 加上/去掉这条边之后的答案 之差的绝对值 然后横着竖 ...
- HDU 1828 Picture(长方形的周长和)
HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4 ...
- hdu 4031 attack 线段树区间更新
Attack Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)Total Subm ...
- hdu 4288 离线线段树+间隔求和
Coder Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- hdu 3016 dp+线段树
Man Down Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
随机推荐
- Linux系列教程(十七)——Linux权限管理之文件系统系统属性chattr权限和sudo命令
上篇博客我们介绍了权限管理的ACL权限,通过设定 ACL 权限,我们为某个用户指定某个文件的特定权限.这篇博客我们将介绍权限管理中用的比较多的两个命令 chattr 和 sudo . 1.设定文件系统 ...
- Java面试题技术类
目录 1.面向对象编程的三大特性是什么? 2.String 和StringBuffer的区别 3.说出ArrayList,Vector, LinkedList的存储性能和特性 4.Collection ...
- C# Dapper 轻量ORM调试对SQLServer
Dapper简介 Dapper只有一个代码文件,完全开源,你可以放在项目里的任何位置,来实现数据到对象的ORM操作,体积小速度快. 使用ORM的好处是增.删.改很快,不用自己写sql,因为这都是重复技 ...
- 讨论.NET Core 配置对GC 工作模式与内存的影响
引出问题: Asp.net core应用在 Kubernetes上内存使用率过高问题分析 https://mp.weixin.qq.com/s/PqhUzvFpzopU7rVRgdy7eg 这篇文章中 ...
- 如何在C#中使用存储过程(SQL Server 2000)
要在C#中使用存储过程,首先看看test表的创建sql语句: create table test55 ( uid int identity(1,1), class1 varchar(20), cl ...
- web前端-----第二弹CSS
web前端之CSS样式 CSS 语法 CSS 规则由两个主要的部分构成:选择器,以及一条或多条声明. ''' selector { property: value; property: value; ...
- 自己动手修改Robotium代码(上)
Robotium作为Android自动化测试框架,还有许多不完善的地方,也不能满足测试人员的所有要求.那么,本文以四个实际中碰到的问题为例,介绍改动Robotium源码的过程. public bool ...
- C# 处理Word自动生成报告 一、概述
经常遇到这样的需求, 生成Word格式的报告, 而不是单纯的一张表格的报表. 就像体检报告一样. 数据来源部分决定采用一个存储过程返回Dataset的方式, 整张报告的数据来源于此Dataset的多 ...
- Python 动态导入模块
动态导入模块 目录结构: zhangsandeMacBook-Air:1110 zhangsan$ tree . . ├── lib │ └── aa.py ├── test1.py lib目录下 ...
- STM32F030如何正确配置IO口的复用功能
本文所使用的单片机型号为STM32F030C8T6. 在030系列的单片机中,PA2引脚除了作为普通的IO引脚用作输入输出功能以外,还可以作为内部外设串口1,串口2,定时器15通道1这三个外设的功能引 ...