POJ 1542 Atlantis(线段树 面积 并)
参考网址:http://blog.csdn.net/sunmenggmail/article/details/7984589
Problem Description
friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.
(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.
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.
2
10 10 20 20
15 15 25 25.5
0
Test case #1
Total explored area: 180.00
题意:题意很简单,就是求矩形面积的交
给定一个矩形的左下角坐标和右上角坐标分别为:(x1,y1)、(x2,y2),对这样的一个矩形,我们构造两条线段,一条定位在x1,它在y坐标的区间是[y1,y2],并且给定一个cover域值为1;另一条线段定位在x2,区间一样是[y1,y2],给定它一个cover值为-1。根据这样的方法对每个矩形都构造两个线段,最后将所有的线段根据所定位的x从左到右进行排序。
上图中,红色的字体表示的是该线段的左右标志,绿色字体为当前更新到当前线段的cover值。刚刚开始的时候,线段树上的cover值都为0,但第一根线段(x==0)插入线段树的之后,我们将线段树上的cover加上该线段的cover,那么,此时线段树上被该线段覆盖的位置上的cover的值就为1,下次再插入第二根线段(x==1)此时发现该线段所覆盖的区间内,有一部分线段树的cover为0,另有一部分为1,仔细观察,但插入第二个线段的时候,如果线段树上cover已经为1的那些区间,和现在要插入的第二根线段之间,是不是构成了并面积?还不明白?看下图,绿色部分即为插入第二根线段后得到的并面积
#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
const int maxn=110;
struct LINE
{
double x, y_down, y_up;
int flag;
bool operator<(const LINE &a)const ///按照x从小到大的顺序排序
{
return x<a.x;
}
}line[2*maxn]; struct TREE
{
double x,y_down, y_up;
int cover; ///用以表示加进线段树中的线段次数
bool flag; ///标记叶子节点
}tree[1000*maxn]; double y[2*maxn]; void build(int i, int l, int r) ///当前节点下标,l , r 线段树建立左右线数组下标
{
tree[i].x = -1; //-1表示该区间已经没有线段
tree[i].cover = 0; //表示该区间上有多少条线段;左边线段加进去则++,右边线段加进去则--
tree[i].y_down = y[l];
tree[i].y_up = y[r];
tree[i].flag = false;
if(l+1==r)
{
tree[i].flag = true; //flag==true表示达到了叶子节点
return;
}
int mid=(l+r)>>1;
build(2*i, l, mid);
build(2*i+1, mid, r);
} double insert(int i, double x, double l, double r, int flag) //flag表示为左边还是右边
{
if ( r<=tree[i].y_down || l>=tree[i].y_up ) return 0;
if (tree[i].flag) /// 叶子节点
{
if (tree[i].cover > 0) /// 该区域的面积存在,且未经计算
{
double temp_x = tree[i].x;
double ans=( x-temp_x )*(tree[i].y_up - tree[i].y_down);
tree[i].cover += flag;
tree[i].x = x; //定位上一次的x
return ans;
}
else ///虽然是叶子节点,但是需要更新当前的线段覆盖标记
{
tree[i].cover += flag;
tree[i].x = x; ///更新最新x
return 0;
}
}
return insert(2*i, x, l, r, flag)+insert(2*i+1, x, l, r, flag); ///不是叶子节点就往下递归
} int main( )
{
// freopen("d:\\in.txt","r",stdin);
int Case=0,n,index;
double x1, y1, x2, y2;
while(~scanf("%d",&n) && n)
{
index = 1;
for (int i=1; i<=n; i++)
{
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
y[index] = y1;
line[index].x = x1;
line[index].y_down = y1;
line[index].y_up = y2;
line[index++].flag = 1; //1表示左边 y[index] = y2;
line[index].x = x2;
line[index].y_down = y1;
line[index].y_up = y2;
line[index++].flag = -1; //-1表示右边
}
sort(&y[1], &y[index]); //把所有的纵坐标按从小到大排序,把1写成了0,WA一次
sort(&line[1], &line[index]);
build(1, 1, index-1);
double ans=0;
for (int i=1;i<index; i++) ///将线line从左向右遍历
ans+=insert(1, line[i].x, line[i].y_down, line[i].y_up, line[i].flag);
printf("Test case #%d\nTotal explored area: %.2f\n\n", ++Case, ans);
}
return 0;
}
POJ 1542 Atlantis(线段树 面积 并)的更多相关文章
- HDU 1542 Atlantis(线段树面积并)
描述 There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. S ...
- POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并
题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...
- POJ 1151 Atlantis 线段树求矩形面积并 方法详解
第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...
- HDU 1542 - Atlantis - [线段树+扫描线]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- hdu 1542 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 1542 Atlantis (线段树扫描线)
大意: 求矩形面积并. 枚举$x$坐标, 线段树维护$[y_1,y_2]$内的边是否被覆盖, 线段树维护边时需要将每条边挂在左端点上. #include <iostream> #inclu ...
- HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- 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 线段树+离散化+扫描线
这次是求矩形面积并 /* Problem: 1151 User: 96655 Memory: 716K Time: 0MS Language: G++ Result: Accepted */ #inc ...
随机推荐
- Storyboard里面的几种Segue区别及视图的切换:push,modal,popover,replace和custom
一.视图切换类型介绍 在storyboard中,segue有几种不同的类型,在iphone和ipad的开发中,segue的类型是不同的. 在iphone中,segue有:push,modal,和cus ...
- officetohtml
http://blog.csdn.net/mcpang/article/details/6817643
- ASP.NET MVC 程序 报错“CS0012: 类型“System.Data.Objects.DataClasses.EntityObject”在未被引用的程序集中定义”的解决办法
运行MVC程序,具体报错信息如下: 解决方法: 打开Web.config在assemblies下加入<add assembly="System.Data.Entity, Version ...
- ORA-27101:shared memory realm does not exist的问题
ORA-27101:shared memory realm does not exist的问题 登陆SQLPlus时出现: ORA-01034:ORACLE not avaiable ORA-2710 ...
- 用c#读取文件内容中文是乱码的解决方法:
用c#读取文件内容中文是乱码的解决方法: //方法1: StreamReader din = new StreamReader(@"C:\1.txt", System.Text.E ...
- ajax用户名案例(重点)
要求:失去焦点时如下效果 主页代码 <body> 用户名:<input type="text" id="a" /><div i ...
- Struts2 - Rest(1)
Struts2提供了一个restful的插件:struts2-rest-plugin-2.3.16.1.jar 这个插件可以把Struts2当做restful来使用,不过它的rest功能目前来说有点“ ...
- 解决SQLite3数据库Error: database disk image is malformed
这种错误的提示一般都是数据库文件出现了问题,具体导致问题的原因不必深究,我们只讨论这种问题的饿解决方法: 比如数据库:test.db 这里还要分两种情况: 情况一: sqlite3 test.db & ...
- docker的一些用法
复制文件,复制进去和复制出来一样用 docker cp 源文件 容器id:路径/目标文件 保存镜像 docker commit 容器id 名字 共享文件(加载vol) docker run -v 宿主 ...
- python学习-day01
一.python介绍: python是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,第一个公开发行版发行于1991年. Python语法简洁清晰,特 ...