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. 手机wifi的mac地址是什么??

    简单来说,每个能够接入网络的设备,无论是平板.手机.电脑.电视都有一个专门的序号,这个序号就被称为MAC,正常来说可以看做是这款设备的唯一标识,手机里的MAC其实是特指Wi-Fi无线网卡的MAC地址. ...

  2. SRS——打开 stream caster

    按照默认的配置编译启动后,发现 stream caster 不起作用,启动时报如下警告: [-- ::][][] stream caster: off 原因是编译SRS时没有打开StreamCaste ...

  3. JS中,跨域调用(本地)另一个项目的方法

    IP地址,因为是本地的项目,所以我一开始写的是127.0.0.1...,但不对.应该写本机的IP地址才对!

  4. <audio>音频标签

    <audio ref="audio" @canplay="ready" @error="error"  @timeupdate=&qu ...

  5. Oracle常用命令复习(备考资料)

    Oracle期末考试复习资料,大概的总结了常用的命令,不包括基础理论知识,有的不太考的东西没有整理.资料整理是在有道云笔记里完成的,在这里重新编辑太麻烦了,就附个链接了. 文档:Oracle命令复习2 ...

  6. 网络编程之TCP三次握手,四次断开

    目录 TCP三次握手 1:上图的名词解释 2:TCP三次握手过程 3:为什么不能改成两次握手? TCP三次握手 1:上图的名词解释 SYN:同步序号.它表示建立连接.TCP规定SYN=1时不能携带数据 ...

  7. 项目根目录下.gitignore

    7.项目根目录下.gitignore  # 此为注释 – 将被 Git 忽略  *.a # 忽略所有 .a 结尾的文件  !lib.a # 但 lib.a 除外  /TODO # 仅仅忽略项目根目录下 ...

  8. 守神漏洞扫描器V1.2

    主界面 指纹利用 漏洞库 怎么说呢,个人感觉这个扫描器跟小哲的Test404Fuzzer差不多~ 就是功能多了旁站查询.C段查询.而且这款工具的exp比Test404Fuzzer的多了几个~ 总体来说 ...

  9. Python学习第八课——函数

    python函数(def) def test(x): # x为形参 y = x + 20 return y # def:定义函数的关键字 # test:函数名 # ():内定义参数 # x+=1:代码 ...

  10. GeoDa绘制疫情地图

    刚学习GeoDa,菜鸟,目前还不能在地图上显示省市名称,求教. 看到丁香医生发布的疫情地图,我也尝试做一下,不过我的shp文件上只有中国大陆的31个省市. 数据来源于丁香医生,截至时间为 2020.1 ...