Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 11558 Accepted Submission(s): 4910

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

【题解】



给定几个矩形的左下角和右上角;求所有矩形的面积(重复部分不能多算);

线段树,扫描线;

扫描线的思路就是假想一条线段从图的最下面往上扫描;

我们计算的是扫描线扫过的所有矩形区域的面积;

盗下图



需要把横坐标离散化下;

然后处理出每个矩形的两条横边(上边和下边,上边记为-1,下边记为1);

然后记录所有横边的纵坐标;

然后以所有横边的纵坐标作为关键字升序排下;

从纵坐标小的开始处理;

处理到①的时候;看下②的高度是多少

然后看一下①->②这个线段范围内;横坐标有哪些区域被矩形占据了;

求出这个占据的长度sum[1](即线段树的第一个节点

然后答案递增sum[1]*(h②-h①);

处理下一条线段;

如果下一条线段是上边。就把它相应的下边对应的横坐标范围减去;下次就不会再处理了;

嘛,多看下代码结合图理解下吧。不会很难

代码中cnt是这个区间内下边比上边多多少条边;

显然如果cnt[rt]==0则表示这个区间内没有需要处理的矩形覆盖的范围;

大于0则表示有一个矩形覆盖到了这个区间。且还没有处理完;

(处理到上边的时候会减去相应下边这段的cnt值);

sum[rt]则表示这个区间内被矩形覆盖的线段长度;

/*
看完代码之后你们可能会对那个r+1和r-1有点疑问;
这样先对询问把r减去1,是为了防止线段树在划分的时候
出现
1-6
被分成
1-5和6..6的情况;
右边那个区间只有1个点;而我们没办法用x[6]-x[6]来表示这段长度;
而左边是a[5]-a[1];显然会少掉一段5..6没被加进去;
因此我们先减去1;
这样就只会分成
1..5这一段;
然后加的时候改为a[6]-a[1]即可;
即a[r+1]-a[l];
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long using namespace std; const int MAXN = 200+10;
const int dx[5] = {0,1,-1,0,0};
const int dy[5] = {0,0,0,-1,1};
const double pi = acos(-1.0); struct hx
{
double l,r,h,k;
}; int n,num = 0,cnt[MAXN<<2];
double sum[MAXN<<2];
vector <double> a;
hx bian[MAXN]; void input_LL(LL &r)
{
r = 0;
char t = getchar();
while (!isdigit(t) && t!='-') t = getchar();
LL sign = 1;
if (t == '-')sign = -1;
while (!isdigit(t)) t = getchar();
while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
r = r*sign;
} void input_int(int &r)
{
r = 0;
char t = getchar();
while (!isdigit(t)&&t!='-') t = getchar();
int sign = 1;
if (t == '-')sign = -1;
while (!isdigit(t)) t = getchar();
while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
r = r*sign;
} bool cmp(hx a,hx b)
{
return a.h<b.h;
} void up_data(int L,int R,int c,int l,int r,int rt)
{
if (L<=l && r<=R)
{
cnt[rt]+=c;
if (cnt[rt])
sum[rt] = a[r+1]-a[l];
else//变成0了也不能认定内部就没有需要处理的区间了;还要加上内部的;
if (l==r)
sum[rt]=0;
else
sum[rt] = sum[rt<<1]+sum[rt<<1|1];
return;
}
int m = (l+r)>>1;
if (L <= m)
up_data(L,R,c,lson);
if (m < R)
up_data(L,R,c,rson);
if (cnt[rt])//有可能内部下边已经处理完了,但是外部还有下边,所以不能直接写成sum[rt]=sum[rt<<1]+sum[rt<<1|1]
sum[rt] = a[r+1]-a[l];
else
if (l==r)
sum[rt] == 0;
else
sum[rt] = sum[rt<<1]+sum[rt<<1|1];
} int main()
{
//freopen("F:\\rush.txt","r",stdin);
input_int(n);
int tt = 0;
while (n!=0)
{
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
a.clear();num = 0;
for (int i = 1;i <= n;i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
a.push_back(x1);
a.push_back(x2);
num++;
bian[num].l = x1,bian[num].r = x2,bian[num].h = y1,bian[num].k = 1;//横线的下边
num++;
bian[num].l = x1,bian[num].r = x2,bian[num].h = y2,bian[num].k = -1;//记录横线的上边
}
sort(a.begin(),a.end());
a.erase(unique(a.begin(),a.end()),a.end());//x轴离散化
sort(bian+1,bian+1+num,cmp);
double ans = 0;
for (int i = 1;i <= num-1;i++)
{
int l = lower_bound(a.begin(),a.end(),bian[i].l)-a.begin();
int r = lower_bound(a.begin(),a.end(),bian[i].r)-a.begin()-1;//先把右端点-1
up_data(l,r,bian[i].k,0,a.size()-1,1);
ans+=sum[1]*(bian[i+1].h-bian[i].h);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++tt,ans);
input_int(n);
}
return 0;
}

【42.49%】【hdu 1542】Atlantis(线段树扫描线简析)的更多相关文章

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

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

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

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

  3. hdu 1542 Atlantis (线段树扫描线)

    大意: 求矩形面积并. 枚举$x$坐标, 线段树维护$[y_1,y_2]$内的边是否被覆盖, 线段树维护边时需要将每条边挂在左端点上. #include <iostream> #inclu ...

  4. hdu 1542 Atlantis(线段树,扫描线)

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

  5. HDU 1542 Atlantis(线段树面积并)

     描述 There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. S ...

  6. POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并

    题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...

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

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

  8. hdu 1542(线段树+扫描线 求矩形相交面积)

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

  9. hdu 1542 Atlantis(段树&amp;扫描线&amp;面积和)

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

随机推荐

  1. python控制台输出带颜色文字的方法

    目地:提高重要信息的可读性,方便用户阅读了. 书写格式如下: #格式: 设置颜色开始 :\033[显示方式;前景色;背景色m #说明: 前景色 背景色 颜色 --------------------- ...

  2. 重磅!容器集群监控利器 阿里云Prometheus 正式免费公测

    Prometheus 作为容器生态下集群监控的首选方案,是一套开源的系统监控报警框架.它启发于 Google 的 borgmon 监控系统,并于 2015 年正式发布.2016 年,Prometheu ...

  3. 2018年DDoS攻击全态势:战胜第一波攻击成“抗D” 关键

    2018年,阿里云安全团队监测到云上DDoS攻击发生近百万次,日均攻击2000余次.目前阿里云承载着中国40%网站,为全球上百万客户提供基础安全防御.可以说,阿里云上的攻防态势是整个中国攻防态势的缩影 ...

  4. Kubernetes排错:用容器的元数据提供新思路

    在这篇文章中,让我们讨论一下Kubernetes中的元数据(Metadata),以及如何利用它来监控系统的性能. 元数据(Metadata) 是一个较为高大上的词.它的含义是"用来描述其他数 ...

  5. 巨蟒python全栈开发-第11阶段 ansible_project6

    今日大纲: 1.计划任务前端页面 2.计划任务新增实现 3.计划任务编辑 4.项目详情 5.文件上传 6.replace模块介绍 1.计划任务前端页面 2.计划任务新增实现 3.计划任务编辑 4.项目 ...

  6. oracle获取中文出现乱码问题解决

    首先搞清楚字符集和字符编码概念,了解oracle字符集原理,请参考一位大神的讲解: ref:http://blog.csdn.net/dbanote/article/details/9158367#c ...

  7. Nacos Committer 张龙:Nacos Sync 的设计原理和规划

    图:Nacos Meetup @杭州 与你同行,抬头便是星空. 本文整理自Nacos Committer 张龙的现场分享,阿里巴巴中间件受权发布. 随着 Nacos 1.0.0 稳定版的发布,越来越多 ...

  8. 在SAE上使用Flask插件

    因为我之前学习的时候使用的是虚拟环境,下载的所有需要用到的插件都在flask这个文件夹里面,SAE上Flask的版本和我本地用的版本对不上,导致有时候import都不对,于是我就把本地的环境直接放到S ...

  9. LightOJ 1269 Consecutive Sum (Trie树)

    Jan's LightOJ :: Problem 1269 - Consecutive Sum 题意是,求给定序列的中,子序列最大最小的抑或和. 做法就是用一棵Trie树,记录数的每一位是0还是1.查 ...

  10. hdu 1430 魔板 (BFS+预处理)

    Problem - 1430 跟八数码相似的一题搜索题.做法可以是双向BFS或者预处理从"12345678"开始可以到达的所有状态,然后等价转换过去直接回溯路径即可. 代码如下: ...