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 ...
随机推荐
- Eclipse: Difference between clean, build and publish
https://stackoverflow.com/questions/5656989/eclipse-difference-between-clean-build-and-publish http: ...
- MYSQL两个数据库字符集保持一致问题
参考这篇文章:https://lzw.me/a/mysql-charset.html 还有一篇官方文档:https://dev.mysql.com/doc/refman/5.7/en/charset. ...
- Docker(二十)-Docker容器CPU、memory资源限制
背景 在使用 docker 运行容器时,默认的情况下,docker没有对容器进行硬件资源的限制,当一台主机上运行几百个容器,这些容器虽然互相隔离,但是底层却使用着相同的 CPU.内存和磁盘资源.如果不 ...
- Oracle备份恢复简单过程以及中间的坑.
Oracle 冷备: 貌似需要dbca创建一致的oracle instance 服务器配置版本尽量相同,安装路径相同. 关闭Oracle服务 将oracle app 目录下的oradata以及有快速闪 ...
- Qt_深入了解信号槽(signal&slot)
转自豆子空间 信号槽机制是Qt编程的基础.通过信号槽,能够使Qt各组件在不知道对方的情形下能够相互通讯.这就将类之间的关系做了最大程度的解耦. 槽函数和普通的C++成员函数没有很大的区别.它们也可以使 ...
- webpack4.x相关笔记整理
概念 Webpack是一个模块打包机,它可以将我们项目中的所有js.图片.css等资源,根据其入口文件的依赖关系,打包成一个能被浏览器识别的js文件.能够帮助前端开发将打包的过程更智能化和自动化. W ...
- 线性代数的本质与几何意义 03. 矩阵与线性变换 (3blue1brown 咪博士 图文注解版)
首先,恭喜你读到了咪博士的这篇文章.本文可以说是该系列最重要.最核心的文章.你对线性代数的一切困惑,根源就在于没有真正理解矩阵到底是什么.读完咪博士的这篇文章,你一定会有一种醍醐灌顶.豁然开朗的感觉! ...
- linux shell $ 特殊变量
$0 #Shell本身的文件名 $1-$n #添加到Shell的各参数值.$1是第1参数.$2是第2参数… $* #所有参数列表.如"$*"用「"」括起来的情 ...
- WINFORM 多条件动态查询 通用代码的设计与实现
经常碰到多条件联合查询的问题,以前的习惯认为很简单总会从头开始设计布局代码,往往一个查询面要费上老半天的功夫,而效果也不咋地. 前段时间做了个相对通用的多条件动态查询面,复用起来还是挺方便的, ...
- python之Map函数
# map()函数使用举例 # 功能:map()接受一个函数f和一个或多个list,将f依次作用在list的每个元素,得到一个新的列表 # 语法:map(方法名,列表,[列表2]) # 注意:map( ...