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(两次扫描线) 周 ...
随机推荐
- canvas绘制旋转图形
将绘制到canvas上的要素进行旋转: 1.绘制时,通过操作画布的坐标轴状态:平移画布原点,旋转坐标轴等,达到旋转图形的目的 2.操作操作DOM元素,直接旋转canvas画布 操作画布的坐标轴状态: ...
- Windows系统下python3中安装pyMysql
python2和python3是不兼容的,在py2中,链接数据库使用的是mysqldb,但在py3中是不能用的. 解决办法就是在py3中数据库使用的模块是pyMysql. 在dos窗口中安装第三方库会 ...
- (二): 基于ZeroMQ的实时通讯平台
基于ZeroMQ的实时通讯平台 上篇:C++分布式实时应用框架 (Cpp Distributed Real-time Application Framework)----(一):整体介绍 通讯平台作为 ...
- ES6中class关键字
1 .介绍 //定义类 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + th ...
- 设置Linux环境的欢迎登陆信息
1.编辑/etc/profile文件添加如下内容: for i in /etc/profile.d/*.sh ; do if [ -r "$i" ]; then if [ &quo ...
- python win32 简单操作
源由 刚开始是帮朋友做一个按键精灵操作旺信的脚本,写完后各种不稳定:后来看到python可以操作win32相关的api,恰好这一段时间正在学习python,感觉练手的时候到了~~~ 下载 要注意Pyt ...
- laravel中with()方法,has()方法和whereHas()方法的区别
with() with()方法是用作"渴求式加载"的,那主要意味着,laravel将会伴随着主要模型预加载出确切的的关联关系.这就对那些如果你想加在一个模型的所有关联关系非常有帮助 ...
- Java多线程之线程池详解
前言 在认识线程池之前,我们需要使用线程就去创建一个线程,但是我们会发现有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因 ...
- 彻底理解线程同步与同步代码块synchronized
public class Demo { public static synchronized void fun1(){ } public synchronized void fun2(){ } pub ...
- 【Java疑难杂症】利用Java核心库实现简单的AOP
Spring是一个十分火热开源框架,而AOP(面向切面编程)则是Spring最重要的概念之一,为了更好的理解和学习AOP的思想,使用核心库来实现一次不失为一个好方法. 首先介绍一下AOP的概念,AOP ...