POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
题意:求矩形面积并
分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化!
把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区间内被覆盖的线段的长度总和
这里线段树的一个结点并非是线段的一个端点,而是该端点和下一个端点间的线段,所以题目中r+1,r-1的地方可以自己好好的琢磨一下
详细分析下扫描线
第一次完全看懂扫描线.
像这题的样例:
这么两个矩形,现在要求它的面积并.
假设我门将横边座位扫描线,即每个矩形有两条扫描线,下扫描线,下扫描线,
每条扫描线我们用结构体
const int MAXN=;
struct seg{
double x1,x2,y;
int flag;
bool operator <(const seg& rsh)const{
return y<rsh.y;
}
}G[MAXN];
来保存,保存这条扫描线的两个横坐标和一个纵坐标,还用flag标记这条扫描线是上边还是下边,下边flag=1,上边flag=-1;
将扫描线都存好后,按照横坐标排序,使得每条边从下到上的顺序(a1,a2,a3,a4)
现在可以边看程序边看这..

将a1插入线段树后计算a1覆盖的总长度sum[1]
则红色部分的面积就可以算出来了,sum[1]*(G[i+1].y-G[i].y)

将a2插入线段树中,计算得到总长度为蓝色部分的底边,sum[1]
则蓝色部分的面积也就可以算出来了sum[1]*(G[i+1].y-G[i].y)

最后将a3插入树中,因为a3是上边,因此把红色的底边给消除了,这是线段树计算得的结果为黄色部分的底边sum[1]
则黄色部分的面积为sum[1]*(G[i+1].y-G[i].y)
如此,把三个部分的面积加起来就是矩形面积并了.这也就是扫描线计算计算面积并的基本过程了!
// File Name: 1151.cpp
// Author: Zlbing
// Created Time: 2013/7/20 14:36:01 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--) #define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 const int MAXN=;
struct seg{
double x1,x2,y;
int flag;
bool operator <(const seg& rsh)const{
return y<rsh.y;
}
}G[MAXN];
double hash[MAXN]; double sum[MAXN<<];
int col[MAXN<<]; void pushup(int rt,int l,int r)
{
if(col[rt])
{
sum[rt]=hash[r+]-hash[l];
}
else if(l==r)sum[rt]=;
else sum[rt]=sum[rt<<]+sum[rt<<|];
} void update(int L,int R,int flag,int l,int r,int rt)
{
if(L<=l&&R>=r)
{
col[rt]+=flag;
pushup(rt,l,r);
return;
}
int m=(l+r)>>;
if(L<=m)update(L,R,flag,lson);
if(R>m)update(L,R,flag,rson);
pushup(rt,l,r);
}
int main()
{
int cas=;
int n;
while(~scanf("%d",&n))
{
if(n==)break;
int xlen=;
double a,b,c,d;
REP(i,,n)
{
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
G[xlen].x1=a,G[xlen].x2=c,G[xlen].y=b,G[xlen].flag=;
hash[xlen]=a;
xlen++;
hash[xlen]=c;
G[xlen].x1=a,G[xlen].x2=c,G[xlen].y=d,G[xlen].flag=-;
xlen++;
}
sort(G,G+xlen);
sort(hash,hash+xlen);
CL(col,);
CL(sum,);
double ans=;
for(int i=;i<xlen-;i++)
{
int l=lower_bound(hash,hash+xlen,G[i].x1)-hash;
int r=lower_bound(hash,hash+xlen,G[i].x2)-hash-;
if(l<=r)update(l,r,G[i].flag,,xlen-,);
ans+=sum[]*(G[i+].y-G[i].y);
}
printf("Test case #%d\n",cas++);
printf("Total explored area: %.2lf\n\n",ans);
}
return ;
}
POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]的更多相关文章
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- POJ 1151 - Atlantis 线段树+扫描线..
离散化: 将所有的x轴坐标存在一个数组里..排序.当进入一条线段时..通过二分的方式确定其左右点对应的离散值... 扫描线..可以看成一根平行于x轴的直线..至y=0开始往上扫..直到扫出最后一条平行 ...
- hdu 4419 线段树 扫描线 离散化 矩形面积
//离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...
- poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)
题目链接 题意:给出n个矩形,每个矩形给左下 和 右上的坐标,求围成的周长的长度. 分析: 首先感谢大神的博客,最近做题经常看大神的博客:http://www.cnblogs.com/kuangbin ...
- hdu1542 线段树扫描线求矩形面积的并
题意: 给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次. 思路: 自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方 ...
- POJ 1151 Atlantis(线段树-扫描线,矩形面积并)
题目链接:http://poj.org/problem?id=1151 题目大意:坐标轴上给你n个矩形, 问这n个矩形覆盖的面积 题目思路:矩形面积并. 代码如下: #include<stdio ...
- POJ 1151 Atlantis 线段树+离散化+扫描线
这次是求矩形面积并 /* Problem: 1151 User: 96655 Memory: 716K Time: 0MS Language: G++ Result: Accepted */ #inc ...
- POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)
题目原网址:http://poj.org/problem?id=1177 题目中文翻译: 解题思路: 总体思路: 1.沿X轴离散化建树 2.按Y值从小到大排序平行与X轴的边,然后顺序处理 如果遇到矩形 ...
- POJ 1151 Atlantis 线段树求矩形面积并 方法详解
第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...
随机推荐
- Call Directory Extension 初探
推荐序 本文介绍了 iOS 10 中的 Call Directory Extension 特性,并且最终 Demo 出一个来电黑名单的 App. 作者:余龙泽,哈工大软件工程大四学生,之前在美图公司实 ...
- android开发之service详解
service作为android的四大组件之一,其重要性可想而知,在开发中,我们经常把一些不需要与用户进行交互的工作放在service中来完成,service运行在后台,这样有些人可能会产生错觉,以为 ...
- 使用JExcel导出excel文件
package org.aaa.portal.tools; import java.io.File; import java.io.IOException; import java.util.List ...
- 使用SqlAlchemy时如何方便的取得dict数据、dumps成Json
使用Sqlalchemy可以方便的从数据库读取出python对象形式的数据(吐槽:说实话对象形式也没多方便,还不如我之前从关系型数据库直接读取出dict形式的数据用起来方便,具体参见我以前的文章htt ...
- HTML5 FileReader读取Blob对象API详解
使用FileReader对象,web应用程序可以异步的读取存储在用户计算机上的文件(或者原始数据缓冲)内容,可以使用File对象或者Blob对象来指定所要读取的文件或数据.其中File对象可以是来自用 ...
- 【转】iOS开发UI篇—程序启动原理和UIApplication
原文 http://www.cnblogs.com/wendingding/p/3766347.html 一.UIApplication 1.简单介绍 (1)UIApplication对象是应用程 ...
- 【vc】14_网络编程_socket编程
1.计算机网络基本知识 最简单的网络程序如图: 提示:IP地址就相当于一个公司的总机号码,端口号就相当于分机号码.在打电话时,拨通总机后,还需要转到分机上. (1)协议 ·为进行网络中的数据交换(通信 ...
- PHP面向对象(OOP):PHP5接口技术(interface)
PHP与大多数面向对象编程语言一样,不支持多重继承.也就是说每个类只能继承一个父类.为了解决这个问题,PHP引入了接口,接口的思想是指定了一个实现了该接口的类必须实现的一系列方法.接口是一种特殊的抽象 ...
- linux 下面 opcache 拓展
PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展,只需要在编译安装的时候, 如果你使用--disable-all参数 禁用了默认扩展的构建, 那么必须使用--enable-opcach ...
- PHP要注意的14个问题
1.页面之间无法传递变量 get,post,session 在最新的php版本中自动全局变量是关闭的,所以要从上一页面取得提交过来得变量要使 用$_GET['foo'],$_POST['foo'],$ ...