题目:
Atlantis
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 23220 Accepted: 8657
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
Source

Mid-Central European Regional Contest 2000
[Submit] [Go Back] [Status] [Discuss]

思路:

这题是我线段树扫描线的第一题,题目给了n个矩形,每个矩形给了左下角右上角的坐标,矩形可能会重叠,求的是矩形最后的面积。因为变化范围比较大,我们要用到离散化,离散化就不说了,重点说一说扫描线的过程:
下面有个矩形

现在假设我们有一根线,从下往上开始扫描

  • 如图所示,我们可以把整个矩形分成如图各个颜色不同的小矩形,那么这个小矩形的高就是我们扫过的距离,那么剩下了一个变量,那就是矩形的长一直在变化。
  • 我们的线段树就是为了维护矩形的长,我们给每一个矩形的上下边进行标记,下面的边标记为1,上面的边标记为-1,每遇到一个矩形时,我们知道了标记为1的边,我们就加进来这一条矩形的长,等到扫描到-1时,证明这一条边需要删除,就删去,利用1和-1可以轻松的到这种状态。
  • 还要注意这里的线段树指的并不是线段的一个端点,而指的是一个区间,所以我们要计算的时候r+1和r-1
  • 再提一下离散化,离散化就是把一段很大的区间映射到一个小区间内,这样会节省大量空间,要进行离散化,我们先对端点进行排序,然后去重,然后二分找值就可以了

具体的请结合代码分析:

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <string>
#include <set>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
#define N 220
#define ll long long
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Seg
{double l,r,h;int f;Seg() {}Seg(double a,double b,double c,int d):l(a),r(b),h(c),f(d) {}bool operator < (const Seg &cmp) const{return h<cmp.h;}
} e[N];
struct node
{int cnt;double len;
} t[N<<2];
double X[N];
void pushdown(int l,int r,int rt)
{if(t[rt].cnt)//当前的边被标记,就把当前的长度加上t[rt].len=X[r+1]-X[l];else if(l==r)//当为一个点的时候长度为0t[rt].len=0;else//其他情况把左右两个区间的值加上t[rt].len=t[rt<<1].len+t[rt<<1|1].len;
}
void update(int L,int R,int l,int r,int rt,int val)
{if(L<=l&&r<=R){t[rt].cnt+=val;//加上标记的值pushdown(l,r,rt);//像下更新节点return;}int m=(l+r)>>1;if(L<=m) update(L,R,lson,val);if(R>m) update(L,R,rson,val);pushdown(l,r,rt);
}
int main()
{int n,q=1;double a,b,c,d;while(~scanf("%d",&n)&&n){mem(t,0);int num=0;for(int i=0; i<n; i++){scanf("%lf%lf%lf%lf",&a,&b,&c,&d);X[num]=a;e[num++]=Seg(a,c,b,1);//矩形下面用1来标记吗X[num]=c;e[num++]=Seg(a,c,d,-1);//上面用-1来标记}sort(X,X+num);//用于离散化sort(e,e+num);//把矩形的边的纵坐标从小到大排序int m=unique(X,X+num)-X;double ans=0;for(int i=0; i<num; i++){int l=lower_bound(X,X+m,e[i].l)-X;//找出离散化以后的值int r=lower_bound(X,X+m,e[i].r)-X-1;update(l,r,0,m,1,e[i].f);ans+=t[1].len*(e[i+1].h-e[i].h);}printf("Test case #%d\nTotal explored area: %.2lf\n\n",q++,ans);}return 0;
}

POJ1151 Atlantis(线段树,扫描线,离散化,矩形面积并)相关推荐

  1. hdu1542 线段树扫描线求矩形面积的并

    题意:       给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次. 思路:       自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方 ...

  2. hdu1828 线段树扫描线求矩形面积的周长

    题意:       给你n个矩形,问你这n个矩形所围成的图形的周长是多少. 思路:       线段树的扫描线简单应用,这个题目我用的方法比较笨,就是扫描两次,上下扫描,求出多边形的上下边长和,然后同 ...

  3. POJ1151(线段树+扫描线求矩形面积并)

    题目:http://poj.org/problem?id=1151 #include <iostream> #include <string.h> #include <a ...

  4. 亚特兰蒂斯【线段树+扫描线+离散化】

    亚特兰蒂斯[线段树+扫描线+离散化] POJ1151.ACwing247 题目: 有几个古希腊书籍中包含了对传说中的亚特兰蒂斯岛的描述. 其中一些甚至包括岛屿部分地图. 但不幸的是,这些地图描述了亚特 ...

  5. 线段树扫描线求矩形周长详解

    线段树扫描线求矩形周长详解 原创 wucstdio 最后发布于2018-04-24 16:12:09 阅读数 841 收藏 发布于2018-04-24 16:12:09 版权声明:本文为博主原创文章, ...

  6. hdu 1542 Atlantis (线段树+扫描线)

    http://acm.hdu.edu.cn/showproblem.php?pid=1542 单纯的线段树+扫描线求面积并,需要离散化. code: #include <cstdlib> ...

  7. 2016 UESTC Training for Data Structures F - 郭大侠与“有何贵干?” CDOJ 1335 线段树 扫描线 离散化

    F - 郭大侠与"有何贵干?" 就是给一个三维空间,和N个长方体,问覆盖K次的体积 x和y都是1e9,但是z是[1,3],所以可以把这个分为两个二维平面,求被覆盖K次的面积,最后加 ...

  8. 线段树 + 扫描线 + 离散化:亚特兰蒂斯

    题目链接:https://www.acwing.com/problem/content/description/249/ 题目: 有几个古希腊书籍中包含了对传说中的亚特兰蒂斯岛的描述. 其中一些甚至包 ...

  9. HDU - 1542 Atlantis(线段树+扫描线)

    题目链接:点击查看 题目大意:给出n个矩形的左下角坐标和右上角坐标,求出其总面积,注意,矩形会重叠,重叠部分只计算一次 题目分析:如果暴力做需要考虑容斥原理,两两矩形组合判断是否重合,十分麻烦而且时间 ...

  10. POJ 1151 Atlantis 线段树+扫描线

    解题思路: 先将y轴进行离散化.n个矩形的2n个横边纵坐标共构成最多2n-1个区间的边界,对这些区间编号,建立起线段树. x轴记录左边和右边,左边时是矩形面积增加,覆盖层数增加边,右边是形面积减少,覆 ...

最新文章

  1. java面试题oracle,2021年度javasqloracle面试题汇总.doc
  2. java 返回值 泛型 继承_java泛型类继承问题?
  3. 快速修改HTML5,HTML5无刷新修改URL(示例代码)
  4. AliOS-Things Visual studio code helloworld 入门
  5. PAT-乙级-1062 最简分数
  6. navigator 携带参数_福州振动时效参数视频,振动时效设备用途
  7. HTML期末作业-香水网站
  8. Django shell保存数据
  9. Javascript屏蔽IE和Firefox浏览器默认按键响应(快捷键功能)
  10. mac 本地安装mysql_mac 本地安装mysql服务
  11. html新建盒子,html+css 盒子模式展示(备查)
  12. 今天有人问,为何汝粉丝这么少?
  13. (转)霍华德·马克斯:警惕那些人人都追捧的事物
  14. EPL许可证人话翻译
  15. javamail 超时_为什么JavaMail连接超时过长
  16. 扰动分析 matlab,扰动材料力学有限元分析:基于MATLAB编程
  17. 威眼(WeaView)企业计算机监管系统如何安装客户端和日常使用
  18. python 泰森多边形边界_泰森多边形
  19. 为什么我对流程情有独钟?
  20. 城堡的emoji表情_和老外聊天,这几个emoji表情不要乱发,内涵太丰富了…

热门文章

  1. 从零搭建一个基于 ELK 的日志、指标收集与监控系统
  2. CIO40: IT人之三观”不正、三十“南”立
  3. 小米鸿蒙os2.0,HarmonyOS 2.0鸿蒙app预约下载-鸿蒙os(手机系统)2.0小米版预约下载_全球下载...
  4. 窄带随机过程(未完成)
  5. 华南农业大学计算机科学导论试卷,2013-2014学年第1学期计导A卷期末考试试卷
  6. TOPSIS算法与熵权法
  7. python与mysql数据库如何连接_Python操作MySQL数据库连接
  8. 搜索智能问答的探索与实践
  9. cadence 快捷键
  10. 新能源汽车赛道日渐拥挤,谁能成为最终的王者?