POJ 1177 Picture(线段树:扫描线求轮廓周长)
题目链接:http://poj.org/problem?id=1177
题目大意:若干个矩形,求这些矩形重叠形成的图形的轮廓周长。
解题思路:这里引用一下大牛的思路:kuangbin
总体思路:
1.沿X轴离散化建树
2.按Y值从小到大排序平行与X轴的边,然后顺序处理
如果遇到矩形下面那条边则插入到线段树中,遇到矩形上面的边则将相应的边删除掉
根据线段树当前的状态统计长度
第二点是本题的核心思想,偶再举个例:
第一次求出的部分很好理解.
第二次求出的为什么会少了中间那部分.那是因为插入的新线段覆盖了第一条,此时线段树返回的长度是新的那一条的长度,将这个值再减去上次的就少了中间那部分
第三次因为是矩形的上边,所以要删除在那条长的线段.此时的线段树返回的则是第一次的长度,将此值减去第二次返回值,再取其负值就是红色X轴那部分了
最后那条X轴的,再补上就行了。
我写的稍微有点不同,不过大概也就是这个思路了。总结一下就是矩形下位边cnt+1,上位边cnt-1,求tree[1].sum,这些步骤跟求矩形面积并是一样的。
然后按照扫描线从小到大一次跟新,ans+=abs(上一次的测度-更新后的测度)。
然后就按x,y方向扫描线各求一遍,加在一起就是总的周长。(好像还是有点问题,就是重边会出错,不会改啊!!!算了,等以后变强了再来改0 0)
这题我没有离散化,因为数据不是很大也没有小数所以就懒得写了。。。
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<string>
#define LC(a) (a<<1)
#define RC(a) (a<<1|1)
#define MID(a,b) ((a+b)>>1)
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=1e4+; struct Node{
int l,r,cnt,sum;//sum为测度
}tree[N**]; struct node{
int l,r,h,flag;
node(){}
node(double a,double b,double c,double d){
l=a;r=b;h=c;flag=d;
}
}a[N],b[N]; bool cmp(node a,node b){
return a.h<b.h;
}
//因为每条线段对应删除的线段是严格出现的,不需要Lazy也就不需要pushdown()
void pushup(int p) {
if(tree[p].cnt>)
tree[p].sum=tree[p].r-tree[p].l+;
else if(tree[p].l==tree[p].r)
tree[p].sum=;
else
tree[p].sum=tree[LC(p)].sum+tree[RC(p)].sum;
} void build(int p,int l,int r){
tree[p].l=l;
tree[p].r=r;
if(l==r){
tree[p].cnt=tree[p].sum=;
return;
}
build(LC(p),l,MID(l,r));
build(RC(p),MID(l,r)+,r);
pushup(p);
} void update(int p,int l,int r,int cnt){
if(l>tree[p].r||r<tree[p].l)
return;
if(l<=tree[p].l&&r>=tree[p].r&&tree[p].cnt!=-){
tree[p].cnt+=cnt;
pushup(p);
return;
}
update(LC(p),l,r,cnt);
update(RC(p),l,r,cnt);
pushup(p);
} int main(){
int n;
while(~scanf("%d",&n)){
int m1=,m2=;
for(int i=;i<=n;i++){
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1+=N,x2+=N,y1+=N,y2+=N;//防止x,y出现负数
a[++m1]=node(x1,x2,y1,);
b[m1]=node(y1,y2,x1,);
a[++m1]=node(x1,x2,y2,-);
b[m1]=node(y1,y2,x2,-);
}
sort(a+,a++m1,cmp);
sort(b+,b++m1,cmp);
//自下往上扫描一遍
build(,,*N-);
int ans=;
for(int i=;i<=m1;i++){
int last=tree[].sum;
int l=a[i].l;
int r=a[i].r-;
update(,l,r,a[i].flag);
ans+=abs(tree[].sum-last);
}
//自左往右扫描一遍
build(,,*N-);
for(int i=;i<=m1;i++){
int last=tree[].sum;
int l=b[i].l;
int r=b[i].r-;
update(,l,r,b[i].flag);
ans+=abs(tree[].sum-last);
}
printf("%d\n",ans);
}
return ;
}
POJ 1177 Picture(线段树:扫描线求轮廓周长)的更多相关文章
- poj 1177 --- Picture(线段树+扫描线 求矩形并的周长)
题目链接 Description A number of rectangular posters, photographs and other pictures of the same shape a ...
- poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)
题目链接 题意:给出n个矩形,每个矩形给左下 和 右上的坐标,求围成的周长的长度. 分析: 首先感谢大神的博客,最近做题经常看大神的博客:http://www.cnblogs.com/kuangbin ...
- POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)
题目原网址:http://poj.org/problem?id=1177 题目中文翻译: 解题思路: 总体思路: 1.沿X轴离散化建树 2.按Y值从小到大排序平行与X轴的边,然后顺序处理 如果遇到矩形 ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- HDU 1828 / POJ 1177 Picture --线段树求矩形周长并
题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...
- Picture POJ - 1177 (线段树-扫描线)
A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wa ...
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- POJ 1177 Picture(线段树周长并)
描述 A number of rectangular posters, photographs and other pictures of the same shape are pasted on ...
- hdu1542 Atlantis 线段树--扫描线求面积并
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...
- hdu1828 Picture(线段树+扫描线+矩形周长)
看这篇博客前可以看一下扫描线求面积:线段树扫描线(一.Atlantis HDU - 1542(覆盖面积) 二.覆盖的面积 HDU - 1255(重叠两次的面积)) 解法一·:两次扫描线 如图我们可以 ...
随机推荐
- BZOJ3123:[SDOI2013]森林——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=3123 https://www.luogu.org/problemnew/show/P3302 树上主 ...
- lighttpd - 配置
Lighttpd core 配置 connection.kbytes-per-second 限制每一个链接的速度etag.use-inode Etag使用i ...
- bzoj3680: 吊打XXX(模拟退火)
题目要求 最小(dis表示绳结到点i的距离),就是个广义费马点的题,模拟退火裸题QAQ 模拟退火就是优化后的爬山算法,一开始先随机一个平均点,接下来如果随机到的点比当前点劣,温度比较高的话也有几率跳过 ...
- Ext之延时加载
大家在多线程下使用extjs时应该遇到过以下情况: 同时渲染几个组件时,如果组件的内容是动态读取的时候,有时会出现后组件内容不是正确的渲染顺序出现的内容.比如同时渲染两个form,form的字段是动态 ...
- 关于Mybatis的@Param注解 及 mybatis Mapper中各种传递参数的方法
原文:https://blog.csdn.net/mrqiang9001/article/details/79520436 关于Mybatis的@Param注解 Mybatis 作为一个轻量级的数 ...
- Ubuntu 16.04使用python3.x相关
下载pip3 Python 3.x版本使用pip3,它会把你想下载的包放到usr/local/lib/python3.5/dist-packages/下,而非usr/local/lib/python2 ...
- 【题解】Weird journey Codeforces 788B 欧拉路
传送门:http://codeforces.com/contest/788/problem/B 好题!好题! 首先图不连通的时候肯定答案是0,我们下面讨论图联通的情况 首先考虑,如果我们每条边都经过两 ...
- Hbase万亿级存储性能优化总结
背景 hbase主集群在生产环境已稳定运行有1年半时间,最大的单表region数已达7200多个,每天新增入库量就有百亿条,对hbase的认识经历了懵懂到熟的过程.为了应对业务数据的压力,hbase入 ...
- footer点击添加active class
//footer点击添加active class var indexFooter= document.querySelectorAll('#index_footer li'); for (var i ...
- 前端PHP入门-001-为什么学习PHP?
写在前面的话 可能不知道能坚持多久,现在的我喜欢纯文字的描述! 希望能坚持写完,也是对自己的一个鞭策! 总顾及别人,那谁来顾及你! 为什么学习PHP? PHP入门简单,学习入门易入手[呵呵,都这么说, ...