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 ...
随机推荐
- ESXi虚拟机开机进入bios的方法
想要修改启动顺序, 发现界面比较难弄 应该是在设置里面有修正. 首先编辑设置 增加如下设置 就可以了.
- GS使用HTTPS登录的设置过程
1. Windows 增加角色服务 服务器配置管理器, 添加角色服务 增加角色功能里面有: 证书颁发机构 证书颁发机构 web注册 2. AD CS配置 主要是next操作 独立ca 根证书 等 3. ...
- Angular 简单的Post
<!DOCTYPE html><html ng-app="myApp"><head lang="en"> <meta ...
- FICO基础知识(三)
成本中心: 成本中心是企业内的最小职责单位,是每一笔费用的具体接收者.创建成本中心主数据时必须将每个成本中心分配给标准层次结构的某个节点,标准层次结构反映了成本中心与成本中心.成本中心与成本中心组.成 ...
- datatime
/把一个日期字符串如“2007-2-28 10:18:30”转换为Date对象 var strArray=str.split(" "); var strDate=str ...
- SpringBoot(十五)_springboot实现预览pdf
最近,项目上要做个打印的东西,还要预览.我想就直接生成pdf预览,然后用户选择打印 于是,昨天找了找资料.一般用itext 进行转pdf.于是我就用springboot试了试,代码比较简单,现在只是简 ...
- 【题解】ID分配
题目描述 您正在处理要为每个客户端分配唯一ID的特定系统的后端.但是,系统是分布式的,并且有许多组件,每个组件都必须能够为客户端分配ID.换句话说,您希望每个组件都使用尽可能少的组件之间的通信来分配I ...
- BZOJ5343[Ctsc2018]混合果汁——主席树+二分答案
题目链接: CTSC2018混合果汁 显然如果美味度高的合法那么美味度低的一定合法,因为美味度低的可选方案包含美味度高的可选方案. 那么我们二分一个美味度作为答案然后考虑如何验证? 选择时显然要贪心的 ...
- MT【228】整数解的个数
求方程$x+y+z=24$的整数解的个数,要求$1\le x\le 5,12\le y\le 18,-1\le z\le12$ 解:设$a_r$是方程$X+Y+Z=r$的满足上述要求的整数解的个数,那 ...
- 自学Zabbix3.12.6-动作Action-Escalations配置
点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 3.12.6 自学Zabbix3.12.6-动作Action-Escalations配置 1. 概 ...