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. 【PAT甲级】1016 Phone Bills (25 分)(结构体排序)

    题意: 输入24个正整数代表从0到23每个小时通话一分钟花费的美分.输入一个正整数N(<=1000),然后输入N组字符串,每个字符串包含客户的名字和通话的时刻以及打出或者挂断的状态. 按照字典序 ...

  2. StringUtils工具类中的isBlank()方法和isEmpty()方法的区别

    1.isBlank()方法 1 public static boolean isBlank(String str) { 2 int strLen; 3 if (str == null || (strL ...

  3. Linux centosVMware LNMP架构介绍、MySQL安装、PHP安装、Nginx介绍

    一. LNMP架构介绍 和LAMP不同的是,提供web服务的是Nginx 并且php是作为一个独立服务存在的,这个服务叫做php-fpm Nginx直接处理静态请求,动态请求会转发给php-fpm   ...

  4. Rcnn/Faster Rcnn/Faster Rcnn的理解

    基于候选区域的目标检测器 1.  滑动窗口检测器 根据滑动窗口从图像中剪切图像块-->将剪切的图像块warp成固定大小-->cnn网络提取特征-->SVM和regressor进行分类 ...

  5. spring mvc绑定参数之 类型转换 有三种方式:

    spring mvc绑定参数之类型转换有三种方式: 1.实体类中加日期格式化注解(上次做项目使用的这种.简单,但有缺点,是一种局部的处理方式,只能在本实体类中使用.方法三是全局的.) @DateTim ...

  6. Python 之并发编程之进程上(基本概念、并行并发、cpu调度、阻塞 )

    一: 进程的概念:(Process) 进程就是正在运行的程序,它是操作系统中,资源分配的最小单位. 资源分配:分配的是cpu和内存等物理资源 进程号是进程的唯一标识 同一个程序执行两次之后是两个进程 ...

  7. Js为Dom元素绑定事件须知

    为异步加载的Dom 元素绑定事件必须在加载完成之后绑定: $('body').load('LearnClickBinding.ashx');$('a').click(function () { ale ...

  8. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 表格:悬停表格

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  9. js 实现去重

    ES6 set去重 Array.from(new Set([1,2,3,3,4,4])) // [1,2,3,4] [...new Set([1,2,3,3,4,4])] // [1,2,3,4] 使 ...

  10. 分享Linux CentOS7 VMware 系统目录结构、 ls命令 、文件类型、alias命令——笔记

    一. 系统目录结构 生成目录树结构: tree -a 显示所有 tree -d 仅显示目录 tree -L n n代表数字..表示要显示几层... tree -f 显示完整路径.. yum insta ...