Atlantis

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

Problem Description
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

 
Input
The input file consists of several test cases. Each test case starts with a line containing a single integer n (1<=n<=100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0<=x1<x2<=100000;0<=y1<y2<=100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.

The input file is terminated by a line containing a single 0. Don’t process it.

 
Output
For each test case, your program should output one section. The first line of each section must be “Test case #k”, where k is the number of the test case (starting with 1). The second one must be “Total explored area: a”, where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.

Output a blank line after each test case.

 
Sample Input
2
10 10 20 20
15 15 25 25.5
0
 
Sample Output
Test case #1
Total explored area: 180.00
 

题目链接:HDU 1542

感觉难点就在如何用点树实现线段上的统计,首先这题是浮点数,肯定要离散化建树(我选的是对X坐标离散化),二分寻找下标当作区间[l,r]。

现在假设有两个区间段:1——2——3 与 3——4——5,但是如果用点树的方式进行更新对前面一个区间+1,后面一个区间-1,那会造成3这个点的覆盖次数变成0,但显然这两个区间在“段”上是连续的,这样更新肯定会出现问题,但是习惯上是写点树而不是段树,那只能对点修改一下,把更新区间的右端R减掉1,每个点表示这个点到后一个点的一段因此前面的两个区间变成了[1,2]与[3,4],这样在点上就不会出现重复的问题了,然后另外一点改动就是在pushup时直接向上传递不用pushdown。

举个例子

$$\begin{array}{c|lll}
{下标}&{0}&{1}&{2}&{3}&{4}&{5}\\
\hline
{实际值}&{3.3}&{9.8}&{12.1}&{19.8}&{24.9}&{33.3}\\
\end{array}$$

这样的一个坐标离散化这时候出现一个线段[9.8~12.1],然后对应离散化的是[1,2-1]即[1,1],但统计len的时候显然是用12.1-9.8=2.3,因此统计时要用X[R+1]-X[L]来作为长度即X[2]-X[1],那这看起来似乎跟前面的刻意把右端点改成R-1矛盾了……既然统计要R+1那前面干嘛要R-1,其实R-1为的是不影响线段树的区间覆盖,但是你是知道实际上要用R来算,由于统计时是不会影响区间覆盖的,因此要还原回去即R=(R-1)+1

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=110;
struct seg
{
int l,mid,r;
int cnt;
double len;
};
struct Line
{
double l,r,h,flag;
bool operator<(const Line &t)const
{
return h<t.h;
}
};
seg T[N<<3];
Line line[N<<1];
double xpos[N<<1]; inline void pushup(int k)
{
if(T[k].cnt)
T[k].len=xpos[T[k].r+1]-xpos[T[k].l];
else
{
if(T[k].l==T[k].r)
T[k].len=0;
else
T[k].len=T[LC(k)].len+T[RC(k)].len;
}
}
void build(int k,int l,int r)
{
T[k].l=l;
T[k].r=r;
T[k].mid=MID(l,r);
T[k].len=0.0;
T[k].cnt=0;
if(l==r)
return ;
build(LC(k),l,T[k].mid);
build(RC(k),T[k].mid+1,r);
}
void update(int k,int l,int r,int flag)
{
if(l<=T[k].l&&T[k].r<=r)
{
T[k].cnt+=flag;
pushup(k);
}
else
{
if(r<=T[k].mid)
update(LC(k),l,r,flag);
else if(l>T[k].mid)
update(RC(k),l,r,flag);
else
update(LC(k),l,T[k].mid,flag),update(RC(k),T[k].mid+1,r,flag);
pushup(k);
}
}
int main(void)
{
int n,i,q=1;
double xa,xb,ya,yb;
while (~scanf("%d",&n)&&n)
{
int cnt_line=0;
for (i=0; i<n; ++i)
{
scanf("%lf%lf%lf%lf",&xa,&ya,&xb,&yb);
xpos[cnt_line]=xa;
line[cnt_line]=(Line){xa,xb,ya,1};
++cnt_line;
xpos[cnt_line]=xb;
line[cnt_line]=(Line){xa,xb,yb,-1};
++cnt_line;
}
sort(xpos,xpos+cnt_line);//X轴坐标排序
sort(line,line+cnt_line);//线段排序 build(1,0,cnt_line); double res=0.0,dh;
int l,r;
for (i=0; i<cnt_line-1; ++i)
{
l=lower_bound(xpos,xpos+cnt_line,line[i].l)-xpos;
r=lower_bound(xpos,xpos+cnt_line,line[i].r)-xpos;
update(1,l,r-1,line[i].flag);
dh=line[i+1].h-line[i].h;
res+=dh*T[1].len;
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",q++,res);
}
return 0;
}

HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)的更多相关文章

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

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

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

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

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

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

  4. hdu 1542 Atlantis(线段树,扫描线)

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

  5. POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]

    题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...

  6. POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并

    题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...

  7. HDU 1542 Atlantis(线段树面积并)

     描述 There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. S ...

  8. hdu 4419 线段树 扫描线 离散化 矩形面积

    //离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...

  9. POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)

    题目原网址:http://poj.org/problem?id=1177 题目中文翻译: 解题思路: 总体思路: 1.沿X轴离散化建树 2.按Y值从小到大排序平行与X轴的边,然后顺序处理 如果遇到矩形 ...

随机推荐

  1. discuz插件开发新手入门 超详细

    作为一个新手,目前也是刚刚玩转discuz的插件功能,好东西不敢独享,就拿出来大家一起分享入门的过程.现在网上很多关于discuz的插件教程都是很简单的教程,原因可能是这个东西是商业化的东西,本着分享 ...

  2. android 中如何分析内存泄漏

    转载:http://blog.csdn.net/fulinwsuafcie/article/details/8363218 前提条件: 1,电脑安装了java 运行环境 2,手机端开启了 USB 调试 ...

  3. Android配置----DDMS 连接真机(己ROOT),用file explore看不到data/data文件夹的解决办法

    Android DDMS 连接真机(己ROOT),用file explore看不到data/data文件夹,问题在于data文件夹没有权限,用360手机助手或豌豆荚也是看不见的. 有以下两种解决方法: ...

  4. [hihoCoder] 博弈游戏·Nim游戏

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 今天我们要认识一对新朋友,Alice与Bob.Alice与Bob总是在进行各种各样的比试,今天他们在玩一个取石子的游戏.在 ...

  5. Java Hour 48 Servlet 简介

    搞Java Web 开发,绕不开的就是Servlet 了.传说Servlet 是一种比JSP 更加古董的动态网页编程技术.在没有JSP 之前,Servlet 同时充当了展现层,业务逻辑层和持久层. 这 ...

  6. 浅谈K-SVD

    由于工作需要,最近刚刚看了一些K-SVD的介绍,这里给自己做一下小节. K-SVD我们一般是用在字典学习.稀疏编码方面,它可以认为是K-means的一种扩展,http://en.wikipedia.o ...

  7. Beaglebone Black的启动

    Beaglebone Black的启动 第1章  准备开始 Beaglebone Black上最显眼的恐怕就是板子两侧的扩展端口,一侧有46个端口,共92个端口Beaglebone Black的启动. ...

  8. Ajax优缺点

    1.页面无刷新,用户体验好: 2.异步通信,迅速的响应能力: 3.按需取数据,减少冗余需求,减少服务器负荷. 4.破坏浏览器后退按钮的正常行为. 5.Ajax的核心是JavaScript对象XmlHt ...

  9. jquery.validate.js使用说明——后台添加用户邮箱功能:非空、不能重复、格式正确

    重点内容为:  jQuery验证控件jquery.validate.js使用说明+中文API[http://www.tuicool.com/articles/iABvI3] 简单教程可以参考[jQue ...

  10. json学习系列(1)-使用json所要用到的jar包下载

    内容来源于互联网. json是个非常重要的数据结构,在web开发中应用十分广泛.每个开发者都应该好好的去研究一下json的底层实现.在使用json之前首先要明白需要哪些jar文件,初次使用的时候很容易 ...