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(两次扫描线) 周 ...
随机推荐
- node调试工具--node-inspector安装
node-inspector安装: npm install --registry=http://r.cnpmjs.org -g cnpm cnpm install -g node-inspector ...
- addEventListener 的事件函数的传递【转载】
addEventListener 参数如下: addEventListener(type, listener[, useCapture]); type,事件名称 listener,事件处理器 useC ...
- 【转】解决memcached启动失败
原文:http://chenzhou123520.iteye.com/blog/1925196 linux上启动Memcache报错: 原因一般有两个, 一个是操作系统里确实没有包含该共享库(lib* ...
- 自建梯子教程:vultr+ssr+SwitchyOmega
1 综述 在饱受蓝灯挂掉之苦半个月后,终于决定自己搭建VPS服务器FQ了.虽然网上VPS服务器教程很多,但是我按照那些教程弄好VPS服务器总是不稳定,用着用着就不能用了.这应该是这次GFW升级带来的后 ...
- 轻松驾驭Tomcat
Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选.对于一个初学者来说,可以这样 ...
- Python 解LeetCode:Intersection of Two Arrays
最近,在用解决LeetCode问题的时候,做了349: Intersection of Two Arrays这个问题,就是求两个列表的交集.我这种弱鸡,第一种想法是把问题解决,而不是分析复杂度,于是写 ...
- socket阻塞IO流程图
单线程 多线程
- 如何优雅的设计React组件
如何优雅的设计 React 组件 如今的 web 前端已被 React.Vue 和 Angular 三分天下,一统江山十几年的 jQuery 显然已经很难满足现在的开发模式.那么,为什么大家会觉得 j ...
- linux终端自定义命令的别名
alias : 给某个命令定义别名. 如:alias gpush='Git push origin HEAD:refs/for/master'这样在终端中,只需要输入 gpush 就ok了.但是只是这 ...
- 特征提取算法的综合实验(多种角度比较sift/surf/brisk/orb/akze)
一.基本概念: 作用:特征点提取在"目标识别.图像拼接.运动跟踪.图像检索.自动定位"等研究中起着重要作用: 主要算法: •FAST ,Machine Learning forHi ...