HDU 1828 Picture(线段树扫描线求周长)
Picture
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4475 Accepted Submission(s): 2207
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.
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.
题目链接:HDU 1828
扫描线第三道题目,都是整数点且范围较小不需要离散化,主要学习了如何求轮廓线的周长(内周长+外周长),有两种方法这里用的是比较好写但是速度慢的一种——横着竖着各做一次扫描线,统计横竖的周长再求和输出,过程和求面积并类似,但是每一次累加的是覆盖长度的改变量即$abs(这一次更新之后的长度-上一次的长度)$,另外要注意一点就是当高度相同时要优先更新底边。
比如这样一组数据:
2
0 0 1 1
0 1 1 2
若不这样做会得到错误答案8,但其实边长只有4+2=6,原因就是错误地把中间的边也当作影响更新长度的情况了,实际是重叠之后两条边会一起抵消掉,刚开始写完debug半天最后发现是建树时没考虑范围要可能是负数……
代码:
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=2e4+7;
struct seg
{
int l,mid,r;
int len,cnt;
};
struct Line
{
int l,r,h,flag;
inline bool operator<(const Line &t)const
{
if(h==t.h)//若高度相等,则底边优先
return flag>t.flag;
return h<t.h;
}
};
seg T[N<<2];
Line xline[N],yline[N]; inline void pushup(int k)
{
if(T[k].cnt)
T[k].len=T[k].r-T[k].l+1;
else
{
if(T[k].l==T[k].r)
T[k].len=0;
else
T[k].len=T[LC(k)].len+T[RC(k)].len;
}
}
void build(int k,int l,int r)
{
T[k].l=l;
T[k].r=r;
T[k].mid=MID(l,r);
T[k].cnt=0;
T[k].len=0;
if(l==r)
return ;
build(LC(k),l,T[k].mid);
build(RC(k),T[k].mid+1,r);
}
void update(int k,int l,int r,int flag)
{
if(l<=T[k].l&&T[k].r<=r)
{
T[k].cnt+=flag;
pushup(k);
}
else
{
if(r<=T[k].mid)
update(LC(k),l,r,flag);
else if(l>T[k].mid)
update(RC(k),l,r,flag);
else
update(LC(k),l,T[k].mid,flag),update(RC(k),T[k].mid+1,r,flag);
pushup(k);
}
}
int main(void)
{
int n,i;
int xa,xb,ya,yb;
int ans,last;
while (~scanf("%d",&n))
{
int cnt=0;
int xR=-INF;
int yR=-INF;
int xL=INF;
int yL=INF;
for (i=0; i<n; ++i)
{
scanf("%d%d%d%d",&xa,&ya,&xb,&yb);
xline[cnt]=(Line){xa,xb,ya,1};
yline[cnt++]=(Line){ya,yb,xa,1};//
xline[cnt]=(Line){xa,xb,yb,-1};
yline[cnt++]=(Line){ya,yb,xb,-1};//
if(xa>xR) xR=xa;
if(xa<xL) xL=xa;
if(xb>xR) xR=xb;
if(xb<xL) xL=xb; if(ya>yR) yR=ya;
if(ya<yL) yL=ya;
if(yb>yR) yR=yb;
if(yb<yL) yL=yb;
}
ans=0;
sort(xline,xline+cnt);
sort(yline,yline+cnt); last=0;
build(1,xL,xR);
for (i=0; i<cnt; ++i)
{
update(1,xline[i].l,xline[i].r-1,xline[i].flag);
ans=ans+abs(T[1].len-last);
last=T[1].len;
} last=0;
build(1,yL,yR);
for (i=0; i<cnt; ++i)
{
update(1,yline[i].l,yline[i].r-1,yline[i].flag);
ans=ans+abs(T[1].len-last);
last=T[1].len;
} printf("%d\n",ans);
}
return 0;
}
HDU 1828 Picture(线段树扫描线求周长)的更多相关文章
- HDU 1828 Picture (线段树+扫描线)(周长并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 给你n个矩形,让你求出总的周长. 类似面积并,面积并是扫描一次,周长并是扫描了两次,x轴一次,y ...
- HDU 1828 Picture (线段树:扫描线周长)
依然是扫描线,只不过是求所有矩形覆盖之后形成的图形的周长. 容易发现,扫描线中的某一条横边对答案的贡献. 其实就是 加上/去掉这条边之前的答案 和 加上/去掉这条边之后的答案 之差的绝对值 然后横着竖 ...
- hdu1828 Picture(线段树+扫描线+矩形周长)
看这篇博客前可以看一下扫描线求面积:线段树扫描线(一.Atlantis HDU - 1542(覆盖面积) 二.覆盖的面积 HDU - 1255(重叠两次的面积)) 解法一·:两次扫描线 如图我们可以 ...
- POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算
求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...
- poj 1177 --- Picture(线段树+扫描线 求矩形并的周长)
题目链接 Description A number of rectangular posters, photographs and other pictures of the same shape a ...
- hdu 1828 Picture(线段树 || 普通hash标记)
http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others) Mem ...
- hdu 1828 Picture(线段树轮廓线)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- hdu 1542(线段树+扫描线 求矩形相交面积)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- hdu 1828 Picture(线段树扫描线矩形周长并)
线段树扫描线矩形周长并 #include <iostream> #include <cstdio> #include <algorithm> #include &l ...
随机推荐
- express-18 路由
简介 路由是网站或Web服务中最重要的一个方面:路由是将请求(由URL和HTTP方法指定)路由到处理它们的代码去的一种机制. 路由过去是基于文件的,这很简单,但不灵活. IA 是指内容的概念性组织.在 ...
- Lost Cows
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9669 Accepted: 6228 Description N (2 ...
- Dapper ORM 用法—Net下无敌的ORM(转)
假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper这款ROM.点击下载Dapper的优势:1,Dapper是一个轻型的ORM类.代码就一个SqlMapper.cs文件,编译后 ...
- Image Transformation in WPF输入日志标题
Image transformation is a process of rotating and scaling images. Rotating Images There are two ways ...
- ural 2071. Juice Cocktails
2071. Juice Cocktails Time limit: 1.0 secondMemory limit: 64 MB Once n Denchiks come to the bar and ...
- Mac OS Storm+Kafka+Zookeeper配置
先补充一个前两天mac配置的文档. 首先确定由jdk scala环境 JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/Cu ...
- Android中使用反应式编程RxJava
GitHut 地址: https://github.com/ReactiveX/RxAndroid (1)RxJava简介: RxJava 是一个在Java虚拟机上实现的响应式扩展库:提供了基于obs ...
- 一个动画 Label (走马观花)
UILabel中一个水平移动的Label UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(10, 10, 300, 300)]; U ...
- BZOJ2844: albus就是要第一个出场
Description 已知一个长度为n的正整数序列A(下标从1开始), 令 S = { x | 1 <= x <= n }, S 的幂集2^S定义为S 所有子集构成的集合. 定义映射 f ...
- UESTC 30 最短路,floyd,水
最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Statu ...