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 ...
随机推荐
- MySQL: Connection Refused,调整 mysql.ini中的 max_connections
连接相同的结构的MySQL数据库,一套库Tomcat启动正常,另一套库一直报Connection Refused. 可以断定是连接数太小了.查找mysql.ini中的 max_connections, ...
- luogu1856
P1856 [USACO5.5]矩形周长Picture 题目背景 墙上贴着许多形状相同的海报.照片.它们的边都是水平和垂直的.每个矩形图片可能部分或全部的覆盖了其他图片.所有矩形合并后的边长称为周长. ...
- cxf Webservice 使用httpClient 调用
package com.wistron.wh.swpc.portal.uitl; import java.io.BufferedInputStream;import java.io.File;impo ...
- python中字典和json的区别
python中,json和dict非常类似,都是key-value的形式,而且json.dict也可以非常方便的通过dumps.loads互转 定义 python中,json和dict非常类似,都是k ...
- asp.net 连接SQL Server 数据库并进行相关操作
asp.net 连接数据库,操作数据库主要需要两个类,一个是SqlConnection,一个是SqlCommand SqlConnection用于连接数据库,打开数据库,关闭数据库. 连接数据库需要特 ...
- scrapy 简单爬虫实验
利用python的模块requests来爬取百度搜索出来的url 使用环境为python3 #!/use/bin/env python # -*- coding:utf-8 -*- import re ...
- ceph 安装过程
安装依赖: yum install -y yum-utils && yum-config-manager --add-repo https://dl.fedoraproject.org ...
- Luogu3835 【模板】可持久化平衡树(fhq-treap)
fhq-treap,也即非旋treap,可以在不进行旋转操作的前提下维护treap.由于不需要旋转,可以对其可持久化. fhq-treap的基本操作是merge和split,并且通过这两个操作实现对t ...
- Codeforces Round #381 (Div. 2)C Alyona and mex
Alyona's mother wants to present an array of n non-negative integers to Alyona. The array should be ...
- MySQL将一张表的某些列数据,复制到另外一张表,并且修改某些内容
MySQL将一张表的某些列数据,复制到另外一张表 INSERT INTO t_topic_content(content,topicId) SELECT content,id FROM t_topi ...