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

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 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

题意是给出诸多矩形的左下角坐标和右上角坐标,问这些矩形一共覆盖的面积。

看了真的是很久很久,终于把这道题的代码搞懂了,趁着对这道题有很多感觉,赶紧记下来。也通过这些题,发现线段树的应用范围真的是广。

实际上就是对每一段的x,求其y的长度,相乘就是对应的面积。最后把所有的面积加起来就是总面积。为了防止可能会发生重复加的面积,使用了线段树的结构。

首先是离散化,把y坐标上的浮点数 变成1 2 3 ---,然后使用对每一条边使用二分查找。

然后线段树中的每一个节点就代表了相应段的y的长度,和之前的线段树一样,线段树的思想就是我要使用哪一段的长度,我再去计算它更新它,这里面的len就代表了这个含义。

然后就是cover,cover就是只有为0的时候去更新它,因为不是0的时候代表着它依然被某个矩形覆盖着,所以不能更新成子节点的长度之和。

dele就是将原来的长度划出掉,cover--,判断为0就更新该点的len。

写到哪里算哪里,看着这段代码,觉得真的很奇妙。

代码:

#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
using namespace std; double y[210]; struct li
{
double x,y1,y2;
bool bleft;
}lines[210]; struct no
{
int L,R;
double len;
int cover; }tree[10000]; bool operator < (const li &n1,const li &n2)
{
return n1.x<n2.x;
} template <class F,class T>
F bin_search(F s,F e,T val)
{
F L = s;
F R = e-1; while(L<=R)
{
F mid = L + (R-L)/2;
if(!(*mid<val || val < *mid))
{
return mid;
}
else if(val < *mid)
{
R = mid -1;
}
else
{
L= mid + 1;
}
}
} void buildtree(int root,int L,int R)
{
tree[root].L=L;
tree[root].R=R; tree[root].len=0;
tree[root].cover=0; if(L!=R)
{
int mid = (L+R)/2;
buildtree(root*2+1,L,mid);
buildtree(root*2+2,mid+1,R);
}
} void inse(int root,int L,int R)
{
if(tree[root].L==L&&tree[root].R==R)
{
tree[root].cover++;
tree[root].len= y[R+1] - y[L];
return;
}
int mid = (tree[root].L + tree[root].R)/2; if(R<=mid)
{
inse(root*2+1,L,R);
}
else if(L>=mid+1)
{
inse(root*2+2,L,R);
}
else
{
inse(root*2+1,L,mid);
inse(root*2+2,mid+1,R);
}
if(tree[root].cover==0)
{
tree[root].len = tree[root*2+1].len + tree[root*2+2].len;
}
} void dele(int root,int L,int R)
{
if(tree[root].L == L && tree[root].R == R)
{
tree[root].cover--;
if(tree[root].cover==0)
{
if(tree[root].L == tree[root].R)
{
tree[root].len=0;
}
else
{
tree[root].len = tree[root*2+1].len + tree[root*2+2].len;
}
}
return;
} int mid = (tree[root].L + tree[root].R)/2;
if(R<=mid)
{
dele(root*2+1,L,R);
}
else if(L>=mid+1)
{
dele(root*2+2,L,R);
}
else
{
dele(root*2+1,L,mid);
dele(root*2+2,mid+1,R);
} if(tree[root].cover==0)
{
tree[root].len = tree[root*2+1].len + tree[root*2+2].len;
}
}
int n; int main()
{
int i,yc,lc,t;
double x1,x2,y1,y2;
t=0;
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
t++;
yc=0;
lc=0;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
y[yc++]=y1;
y[yc++]=y2; lines[lc].x=x1;
lines[lc].y1=y1;
lines[lc].y2=y2;
lines[lc].bleft=true;
lc++; lines[lc].x=x2;
lines[lc].y1=y1;
lines[lc].y2=y2;
lines[lc].bleft=false;
lc++;
}
sort(lines,lines+lc);
sort(y,y+yc);
yc=unique(y,y+yc)-y; buildtree(0,0,yc-1-1);
double Area=0; for(i=0;i<lc-1;i++)
{
int L=bin_search(y,y+yc,lines[i].y1)-y;
int R=bin_search(y,y+yc,lines[i].y2)-y; if(lines[i].bleft)
{
inse(0,L,R-1);
}
else
{
dele(0,L,R-1);
}
Area += tree[0].len*(lines[i+1].x-lines[i].x);
}
printf("Test case #%d\n",t);
printf("Total explored area: %.2lf\n",Area);
printf("\n");
} //system("pause");
return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

POJ 1151:Atlantis 线段树+扫描线的更多相关文章

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

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

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

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

  3. POJ 1151 Atlantis 线段树求矩形面积并 方法详解

    第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...

  4. POJ 1151 Atlantis 线段树+离散化+扫描线

    这次是求矩形面积并 /* Problem: 1151 User: 96655 Memory: 716K Time: 0MS Language: G++ Result: Accepted */ #inc ...

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

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

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

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

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

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

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

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

  9. POJ1151 Atlantis 线段树扫描线

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

随机推荐

  1. 图形数据写入数据库,Filletream

    图形数据写入数据库 用FileStream对象读模式打开图形文件 Dim 文件对象 As New FileStream(图形文件名, FileMode.Open, FileAccess.Read) 定 ...

  2. mysql 通过localhost可以连接IP连接不上

    因为MySQL默认没开 所以需要手动设置 开MySQL启远程连接的功能,在MySQL服务器控制台上执行以下命令: 设置权限: grant all privileges on *.* to 用户名@&q ...

  3. Pytorch 初次使用nn包

    计算图和autograd是十分强大的工具,可以定义复杂的操作并自动求导:然而对于大规模的网络,autograd太过于底层. 在构建神经网络时,我们经常考虑将计算安排成层,其中一些具有可学习的参数,它们 ...

  4. mysql设置timpstamp的默认值为 '0000-00-00 00:00:00' 时报错

    问题:mysql设置timpstamp的默认值为 '0000-00-00 00:00:00' 时报错: ERROR 1067 (42000): Invalid default value for 'u ...

  5. osgb的顶点,纹理,索引,UV读取与存储

    virtual void apply(osg::Geode& node) { ; i < node.getNumDrawables(); i++) { osg::Geometry* ge ...

  6. struts的错误回显

  7. 运算符 Operator 及优先级

    算数运算符 + - * / ** % /表示自然除,结果是浮点数.//为整除.python2.x版本/和//都是整除. 位运算符 & | ~ ^ << >> <& ...

  8. hdfs的bug纪录, Unexpected block state

      今早遇到一个bug,提交 spark job 失败.说 hdfs 在 safe mode状态,不允许创建和删除文件. 然后发现 hdfs 的日志文件不断滚动,几乎每秒钟100M的速度打日志,当时没 ...

  9. 前端学习笔记系列一:4 vue中@click.native

    .native - listen for a native event on the root element of component. 作用:[给组件绑定原生事件] 例子:如果使用router-l ...

  10. 多门店4s管理系统

    下载 系统登录用户名与密码:manage/123456