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 ...
随机推荐
- mvc-6依赖管理
CommonJS CommonJS规范,主要解决命名空间管理模块和用一套标准的编程模式来加载模块: 很快成为了JavaScript模块写法的事实标准: 它包含IO接口,底层的套接字流,以及单元测试等标 ...
- HTTP基础09--web(1)
Web 应用 通过 Web 提供功能的 Web 应用 原本应用 HTTP 协议的 Web 的机制就是对客户端发来的请求,返回事前准备好的内容.可随着 Web 越来越普及,仅靠这样的做法已不足以应对所有 ...
- Swift3.0语言教程使用编码创建和初始化字符串
Swift3.0语言教程使用编码创建和初始化字符串 使用编码创建和初始化字符串 创建和初始化字符串除了可以使用上文中提到的方法外,还可以使用init(coder:)方法,此方法一般不常使用,其语法形式 ...
- 移动网站中,用canvas,svg比用图片好?
1.Svg可以单独作为文件打开,在AI里做矢量图形,保存图层路径,即可另存为Svg文件. (1) Path语法:命令+参数.大写字母表示坐标参数为绝对位置,小写字母表示坐标参数为相对位置(即上次画笔结 ...
- TStringList 常用操作
//TStringList 常用方法与属性: var List: TStringList; i: Integer; begin List := TStringList.Create; ...
- 【bzoj3624】【apio2008】免费道路
2016/06/25 诸老师讲的图论,听了这道题很想写一下,但是看来要留到期末考后了. 07/01 有的标记是说生成树,有的是并查集...然而我只是觉得这棵奇怪的生成树蛮精妙的... 题目比较难过的只 ...
- [BZOJ2599][Race][IOI2011]点分治
这是为了真正去学一下点分治..然后看了迪克李的ppt 又是一道写(改)了很久的题..终于ac了 1354799 orzliyicheng 2599 Accepted 31936 kb 23584 ms ...
- LightOJ1036 A Refining Company(DP)
题目大概说有一个n*m的格子地图,每个格子有铀或者镭矿.地图最北面的镭矿加工厂,最西面有铀矿加工厂,而要通过在格子里铺设由南向北(镭)或由东向西(铀)的轨道来送矿物到加工厂.一个格子只能铺设一种轨道, ...
- BZOJ1946 : [Ceoi2006]ANTENNA
首先通过随机增量法求出最小覆盖圆,作为答案的上界. 然后二分答案,检验的时候枚举每个点作为原点,求出其他每个点被包括在圆内的角度区间,然后扫描线即可. 时间复杂度$O(Tn^2\log n)$. #i ...
- BZOJ3764 : Petya的序列
首先如果一段连续子序列里没有任何幸运数,那么显然可以缩成一个点. 设幸运数个数为$m$,那么现在序列长度是$O(m)$的,考虑暴力枚举$R_1$,然后从右往左枚举$L_1$. 每次碰到一个幸运数,就将 ...