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. Java内存分配和内存管理

    首先是概念层面的几个问题: Java中运行时内存结构有哪几种? Java中为什么要设计堆栈分离? Java多线程中是如何实现数据共享的? Java反射的基础是什么? 然后是运用层面: 引用类型变量和对 ...

  2. Eclipse中android工程C++文件中出现的莫名其妙的错误

    大多数是std库相关的问题,例如 vector<int> v; v.push_back(23);//这句语法是没有错误的,但是每次执行Run As的时候就会报错 尝试1:在工程名右键-Cl ...

  3. CentOS下配置Hadoop集群:java.net.NoRouteToHostException: No route to host问题的解决

    我用的是hadoop 1.2.1 遇到的问题是: hadoop中datanode无法启动,报Caused by: java.net.NoRouteToHostException: No route t ...

  4. SQL with as

    姓名 课程 分数 张三 语文 张三 数学 张三 物理 李四 语文 李四 数学 李四 物理 先看下面一个嵌套的查询语句 ) 上面的查询语句使用了一个子查询.虽然这条SQL语句并不复杂,但如果嵌套的层次过 ...

  5. GBK、GB2312、iso-8859-1之间的区别

    转自:http://blog.csdn.net/jerry_bj/article/details/5714745 GBK.GB2312.iso-8859-1之间的区别 GB2312,由中华人民共和国政 ...

  6. 关于MFC监听器的相关了解

    最近有个项目,所搭框架为了减少耦合,希望MainFrame中View不依赖于Mainframe,即MainFrame中含有view类而view中不会包含MainFrame的相关信息. 现在遇到一个问题 ...

  7. 怎么在手机上查看sqlite db

    在 从 百度应用 下载“SQLite编辑器(SQLite Editor)” 安装到手机上.前体是 手机已经Root(可以用360一键Root软件进行root).

  8. JSON浅总

    我们在以前的学习中了解到XML是一种结构化的数据表示方式,一种可扩展标记语言!可以把XML理解成一个微型的结构化的小的数据库,保存一些小型的数据和传输数据,有严格的显示限制.但是XML语句有些冗长和繁 ...

  9. 《大话》之第三者家族 代理 Vs 中介者

    前两天,有个同学突然问我说:"我感觉代理模式和中介者模式不好区分,你能给我讲讲吗?" 刚开始还没敢张嘴,因为他突然一问,我貌似也不知道,经过整理,现在将结果贴出来,请大家共享 代理 ...

  10. TCP和UDP Socket

    1.tcp协议的编程 * 1:客户端.步骤  *         1:创建Socket对象,构造方法里需要指定服务端的ip地址和端口.  *         Socket socket = new S ...