英文题面,我就只放个传送门了。

Solution

   题意是算矩形面积并,这是扫描线算法能解决的经典问题。

  算法的大致思想是,把每一个矩形拆成上边下边(以下称作扫描线),每条扫描线有四个参数l,r,h,v。l和r为它的左右端点的横坐标,h为扫描线的纵坐标,v下面再解释。

  然后把扫描线按h从小到大排序,想一想,所有相邻扫描线之间的有效面积(即被矩形覆盖的面积)加起来是不是就是ans?

  怎么求呢?我们从下往上处理,设当前处理到第i条扫描线,设第i条扫描线与第i+1条扫描线之间的有效面积为s,那么s=(h[i+1]-h[i])*此时x轴被覆盖的长度。

  考虑用线段树来维护这个“x轴被覆盖的长度“,处理到第i条扫描线时,就把区间[l[i],r[i]]覆盖一次。但是这个覆盖是有时限的,当扫到某一条上边时,它对应的下边所产生的覆盖就应该被消去。

  为了方便地处理,我们把下边的v值设为1,上边的v值设为-1,这样修改时直接把区间[l[i],r[i]]的覆盖次数加v就好了。

  具体实现时,x坐标要离散化,线段树中用cnt来表示区间被覆盖的次数,sum来表示区间(当然都是在x轴上)内的覆盖长度。

  注意两点:

  1. 线段树上一个叶子节点i实际上表示的是x轴上[i,i+1]这一段,因此线段树只需要n-1个叶子节点。
  2. 由于我们只需要查询sum[1],所以update找到需修改的区间可以直接pushup,并且不用pushdown。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
struct line{
double l,r,h;int v;
line(){}
line(double a,double b,double c,int d):l(a),r(b),h(c),v(d){}
bool operator < (const line &tmp)const{return h<tmp.h;}
}L[N];
int cnt[N<<];
double X[N],sum[N<<];
#define tl id<<1
#define tr id<<1|1
#define mid ((l+r)>>1)
#define lson tl,l,mid
#define rson tr,mid+1,r
void pushup(int id,int l,int r){
if(cnt[id]) sum[id]=X[r+]-X[l];
else if(l==r) sum[id]=;
else sum[id]=sum[tl]+sum[tr];
}
void update(int id,int l,int r,int ll,int rr,int v){
if(ll<=l&&r<=rr){
cnt[id]+=v;
pushup(id,l,r);
return ;
}
if(ll>mid) update(rson,ll,rr,v);
else if(rr<=mid) update(lson,ll,rr,v);
else update(lson,ll,rr,v),update(rson,ll,rr,v);
pushup(id,l,r);
}
int n,m,cas;
int main(){
while(~scanf("%d",&n)&&n){
m=;memset(cnt,,sizeof cnt);memset(sum,,sizeof sum);
for(int i=;i<n;++i){
double a,b,c,d;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
L[m]=line(a,c,b,);
X[m++]=a;
L[m]=line(a,c,d,-);
X[m++]=c;
}
sort(&L[],&L[m]);
sort(&X[],&X[m]);n=unique(&X[],&X[m])-X;
double s=;
for(int i=;i<m;++i){
int l=lower_bound(&X[],&X[n],L[i].l)-X,r=lower_bound(&X[],&X[n],L[i].r)-X-;
update(,,n-,l,r,L[i].v);
s+=sum[]*(L[i+].h-L[i].h);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas,s);
//POJ上提交G++的同学请改为%.2f
}
return ;
}

扫描线

[POJ1151][HDU1542]Atlantis(线段树,扫描线)的更多相关文章

  1. hdu1542 Atlantis 线段树--扫描线求面积并

    There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...

  2. HDU 1542 - Atlantis - [线段树+扫描线]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...

  3. POJ1151 Atlantis 线段树扫描线

    扫描线终于看懂了...咕咕了快三个月$qwq$ 对于所有的横线按纵坐标排序,矩阵靠下的线权值设为$1$,靠上的线权值设为$-1$,然后执行线段树区间加减,每次的贡献就是有效宽度乘上两次计算时的纵坐标之 ...

  4. HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  5. 【42.49%】【hdu 1542】Atlantis(线段树扫描线简析)

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s) ...

  6. POJ 1151 - Atlantis 线段树+扫描线..

    离散化: 将所有的x轴坐标存在一个数组里..排序.当进入一条线段时..通过二分的方式确定其左右点对应的离散值... 扫描线..可以看成一根平行于x轴的直线..至y=0开始往上扫..直到扫出最后一条平行 ...

  7. POJ 1151:Atlantis 线段树+扫描线

    Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19374   Accepted: 7358 Descrip ...

  8. hdu 1542 Atlantis (线段树扫描线)

    大意: 求矩形面积并. 枚举$x$坐标, 线段树维护$[y_1,y_2]$内的边是否被覆盖, 线段树维护边时需要将每条边挂在左端点上. #include <iostream> #inclu ...

  9. hdu1542 Atlantis (线段树+矩阵面积并+离散化)

    There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...

  10. hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

随机推荐

  1. python之paramiko 远程执行命令

    有时会需要在远程的机器上执行一个命令,并获得其返回结果.对于这种情况,python 可以很容易的实现. 1 .工具 Python paramiko 1) Paramiko模块安装 在Linux的Ter ...

  2. 【js】面向对象学习资料

    1.面向对象模式: https://m.jb51.net/article/74549.htm 2.面向对象基础篇 http://www.cnblogs.com/chiangchou/p/js-oop1 ...

  3. SpringCloud 配置文件 application.yml和 bootstrap.yml区别

    前言: SpringBoot默认支持properties和YAML两种格式的配置文件.前者格式简单,但是只支持键值对.如果需要表达列表,最好使用YAML格式.SpringBoot支持自动加载约定名称的 ...

  4. 进程、线程、协程的基本解析(python代码)

    进程什么是进程?程序就是一堆放在磁盘上的代码,进程是一段程序的运行过程正规点说,进程一般由程序.数据集.进程控制块三部分组成 什么进程切换?进程切换是,一个正在运行的进程被中断,操作系统指定另一个进程 ...

  5. Tomcat设置默认启动项目

    Tomcat设置默认启动项目 Tomcat设置默认启动项目,顾名思义,就是让可以在浏览器的地址栏中输入ip:8080,就能访问到我们的项目.具体操作如下:     1.打开tomcat的安装根目录,找 ...

  6. 基于Dockerfile搭建JAVA Tomcat运行环境

    前言 在第一篇文字中,我们完全人工方式,一个命令一个命令输入,实现一个java tomcat运行环境,虽然也初见成效,但很累人.如果依靠依靠脚本构建一个Tomcat容器实例,一个命令可以搞定,何乐而不 ...

  7. struct:二进制数据结构的打包与解包

    介绍 struct模块包括一些函数,这些函数可以完成字节串与原生Python数据类型(如数字和字符串)之间的转换 函数与Struct类 struct提供了一组处理结构值的模块级函数,另外还有一个Str ...

  8. MySQL 异地 双机房同步之otter

    一.背景: 阿里巴巴B2B公司,因为业务的特性,卖家主要集中在国内,买家主要集中在国外,所以衍生出了杭州和美国异地机房的需求, 同时为了提升用户体验,整个机房的架构为双A,两边均可写,由此诞生了ott ...

  9. SSM项目无法解析JSP页面

    JSP页面显示标头<%@ page language="java" contentType="text/html; charset=UTF-8" page ...

  10. PassengerNginxdebian快速部署Rails

    Passenger/Nginx/Debian快速部署Rails   PassengerNginxdebian快速部署Rails     安装所需的linux包 sudo apt-get install ...