HDU - 1828 Picture
题意
多个矩形重叠在一起,求出轮廓线的长度。
分析
把矩形分成横线和竖线来处理。现在分析横线的,竖线同理。矩形的坐标都是整数,且范围不大,故此题不需要离散化。从下往上扫描横线,每遇到一条横线,就计算长度,矩形的下边标为1,上边标为-1。具体计算方法是此次区间的总覆盖长度与上次区间长度相比,若没有变化,则说明新加入的横线是重叠的。故每次计算的答案便是两者之差的绝对值。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include <queue>
#include <vector>
#include<bitset>
#include<map>
#include<deque>
using namespace std;
typedef long long LL;
const int maxn = ;
const int mod = +;
typedef pair<int,int> pii;
#define X first
#define Y second
#define pb push_back
//#define mp make_pair
#define ms(a,b) memset(a,b,sizeof(a))
const int inf = 0x3f3f3f3f;
#define lson l,m,2*rt
#define rson m+1,r,2*rt+1 struct edge{
int l,r,h,f;
}ex[*maxn],ey[maxn*]; struct node{
int l,r,cover,len;
int mid(){
return (l+r)>>;
}
}tree[maxn*]; int cmp(edge a,edge b){
return a.h<b.h;
} void build(int l,int r,int rt){
tree[rt].l=l,tree[rt].r=r;
tree[rt].len=tree[rt].cover=;
if(l+==r) return;
int mid = tree[rt].mid();
build(l,mid,rt<<);
build(mid,r,rt<<|);
} void push_up(int rt){
if(tree[rt].cover){
tree[rt].len=tree[rt].r-tree[rt].l;
}else if(tree[rt].l+==tree[rt].r){
tree[rt].len=;
}else{
tree[rt].len=tree[rt<<].len+tree[rt<<|].len;
}
return;
} void update(edge e,int rt){
if(tree[rt].l==e.l&&tree[rt].r==e.r){
tree[rt].cover+=e.f;
push_up(rt);
return;
}
int m=tree[rt].mid();
if(e.r<=m) update(e,rt<<);
else if(e.l>=m) update(e,rt<<|);
else{
edge temp = e;
temp.r=m;
update(temp,rt<<);
temp = e;
temp.l=m;
update(temp,rt<<|);
}
push_up(rt);
}
int ans;
void work(int l,int r,edge seg[],int n){
build(l,r,);
int prelen=;
for(int i=;i<n;i++){
update(seg[i],);
ans += abs(tree[].len-prelen);
prelen=tree[].len;
}
} int main(){
int n,x1,x2,y1,y2;
while(~scanf("%d",&n)){
if(n==){
puts("");
continue;
} int maxx,maxy,minx,miny;
maxx=maxy=-inf,minx=miny=inf;
int cnt=;
for(int i=;i<n;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
//横向
ex[cnt].l=ex[cnt+].l=x1,
ex[cnt].r=ex[cnt+].r=x2,
ex[cnt].h=y1,ex[cnt+].h=y2,
ex[cnt].f=,ex[cnt+].f=-; ey[cnt].l=ey[cnt+].l=y1,
ey[cnt].r=ey[cnt+].r=y2,
ey[cnt].h=x1,ey[cnt+].h=x2,
ey[cnt].f=,ey[cnt+].f=-;
cnt+=; maxx=max(maxx,max(x1,x2));
minx=min(minx,min(x1,x2));
miny=min(miny,min(y1,y2));
maxy=max(maxy,max(y1,y2));
} sort(ex,ex+cnt,cmp);
sort(ey,ey+cnt,cmp);
ans=;
work(minx,maxx,ex,cnt);
work(miny,maxy,ey,cnt);
printf("%d\n",ans);
}
return ;
}
还有一种更好的做好,参见http://www.cnblogs.com/scau20110726/archive/2013/04/13/3018687.html
同时计算横线和竖线
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 5010
#define MAX 10100
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1) struct segment{
int l,r,h,v;
}s[*N];
struct node{
int l,r,lp,rp,cnt,len,num;
int mid()
{ return (l+r)>>; }
}t[*MAX*]; int cmp(struct segment p ,struct segment q)
{
return p.h<q.h;
} void build(int l ,int r, int rt)
{
t[rt].l=l; t[rt].r=r;
t[rt].cnt=t[rt].len=;
t[rt].lp=t[rt].rp=t[rt].num=;
if(l==r) return ;
int mid=t[rt].mid();
build(l,mid,lch(rt));
build(mid+,r,rch(rt));
} void cal(int rt)
{
if(t[rt].cnt)
{
t[rt].len=t[rt].r-t[rt].l+;
t[rt].lp=t[rt].rp=;
t[rt].num=;
}
else if(t[rt].l == t[rt].r) //叶子
{
t[rt].len=;
t[rt].lp=t[rt].rp=;
t[rt].num=;
}
else
{
t[rt].len=t[lch(rt)].len+t[rch(rt)].len;
t[rt].lp=t[lch(rt)].lp;
t[rt].rp=t[rch(rt)].rp;
t[rt].num=t[lch(rt)].num + t[rch(rt)].num - (t[lch(rt)].rp&t[rch(rt)].lp);
}
} void updata(int l ,int r ,int v ,int rt)
{
if(t[rt].l==l && t[rt].r==r) //目标区间
{
t[rt].cnt += v;
cal(rt);
return ;
}
int mid=t[rt].mid();
if(r<=mid) updata(l,r,v,lch(rt));
else if(l>mid) updata(l,r,v,rch(rt));
else
{
updata(l,mid,v,lch(rt));
updata(mid+,r,v,rch(rt));
}
cal(rt);
} int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
if(n==)
{ puts(""); continue; }
int i,maxx,minx,m;
for(i=,m=,maxx=-MAX,minx=MAX; i<n; i++,m+=)
{
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
maxx=max(maxx,x2);
minx=min(minx,x1);
s[m].l=x1; s[m].r=x2; s[m].h=y1; s[m].v=;
s[m+].l=x1; s[m+].r=x2; s[m+].h=y2; s[m+].v=-;
}
sort(s,s+m,cmp);
build(minx,maxx-,);
int res= , prelen=;
s[m]=s[m+]; //每次处理循环的最后一次
for(int i=; i<m; i++)
{
updata(s[i].l,s[i].r-,s[i].v,);
res += abs(t[].len-prelen); //计算横线部分
res += (s[i+].h-s[i].h)*(*t[].num); //计算竖线部分
prelen=t[].len;
}
printf("%d\n",res);
}
return ;
}
HDU - 1828 Picture的更多相关文章
- HDU 1828 Picture(长方形的周长和)
HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4 ...
- HDU 1828 Picture(线段树扫描线求周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- 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”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- HDU 1828 Picture (线段树+扫描线)(周长并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 给你n个矩形,让你求出总的周长. 类似面积并,面积并是扫描一次,周长并是扫描了两次,x轴一次,y ...
- 51nod 1206 && hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)
1206 Picture 题目来源: IOI 1998 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 给出平面上的N个矩形(矩形的边平行于X轴 ...
- hdu 1828 Picture 切割线求周长
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- hdu 1828 Picture(线段树轮廓线)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算
求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...
- (中等) HDU 1828 Picture,扫描线。
Problem Description A number of rectangular posters, photographs and other pictures of the same shap ...
随机推荐
- Under the same directory(folder) copy or rename with the different extension name
@echo offsetlocal EnableDelayedExpansionfor /f "delims=" %%i in ('dir *.vm /q/s/b') do ( c ...
- laravel 在nginx服务器上除了首页其余都是404的问题
nginx对应站点的.conf配置文件添加如下代码 location / { try_files $uri $uri/ /index.php$is_args$query_string; #语法: tr ...
- ubuntu软件安装位置
有时候需要配置ubuntu安装的软件,一般安装软件都是使用apt-get install.那么安装完后,软件的安装目录在哪里呢,可执行文件又放在哪里呢. A.下载的软件的存放位置:/var/cache ...
- js對象構造
創建對象的3種方式: 1. var a=new Object() a.attributes=“1”: 2. var a={attributes:"1",aa:"2&quo ...
- FFT ip core
The FFT core provides four architecture options to offer a trade-off权衡取舍 between core size andtransf ...
- BZOJ2215[Poi2011]Conspiracy——2-SAT+tarjan缩点
题目描述 Byteotia的领土被占领了,国王Byteasar正在打算组织秘密抵抗运动.国王需要选一些人来进行这场运动,而这些人被分为两部分:一部分成为同谋者活动在被占领区域,另一部分是后勤组织在未被 ...
- Laravel框架简单的用户管理[CURD]操作
一个基于laravel和bootstrap的简单的用户管理,适合刚入门的我们,在做的过程中可以加深自己对laravel基础理解,里面存在一些问题,还未修改,比如css和js的引入,表单提交地址等不规范 ...
- tmux的使用
tmux的使用 1: tmux的介绍 tmux是一个优秀的终端多路复用软件,类似GNU Screen,但来自于OpenBSD,采用BSD授权.使用它最直观的好处就是,通过一个终端登录远程主机并 ...
- SharePoint 2013 首页修改
最近客户要求统一首页的风格,所以对各网站的首页进行了统一的修改. 1. 左边导航菜单修改: 修改的地方: Site Settings –> Look and feel –> Navigat ...
- 如何安装/卸载workflow manager 1.0
安装 1. 配置文件: <Workflow> <!--http://msdn.microsoft.com/en-us/library/windowsazure/jj193269(v= ...