博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 1542 Atlantis[扫描线]
阅读量:6449 次
发布时间:2019-06-23

本文共 4054 字,大约阅读时间需要 13 分钟。

Time Limit: 2000/1000 MS (Java/Others)  

Memory Limit: 65536/32768 K (Java/Others)

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 (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坐标进行保存,然后构建一棵线段树,维护X区间上每两个点的距离(差)。将一个矩形的左右两个横坐标在X中的位置添加到线段树中进行区间维护,这样线段树的根节点的值就是该条水平线上的长度。如果一个矩形的边是下面的边,就把这条边的两个坐标加到区间中,如果是上面的边的话就把它从线段树上去掉。

 

#include "bits/stdc++.h"#define lson o<<1, l, mid #define rson o<<1|1, mid+1, r#define ll o<<1#define rr o<<1|1using namespace std;const int maxn = 4000 + 10;struct Line {    double l, r, h;//每条线的左右横坐标 纵坐标    int f;//标明边是上边还是下边} edge[maxn];struct Node {    int l, r, s;//区间左端点 右端点 是否被访问    double len;//区间长度} q[maxn*10];int N;double X[maxn];bool cmp(Line a, Line b) {
return a.h < b.h;}void push_up(int o) { //线段在区间的时候 且为添加线段 if (q[o].s) q[o].len = X[q[o].r+1]-X[q[o].l]; //如果删除的是一个叶子节点 else if (q[o].l == q[o].r) q[o].len = 0; //删除节点 或者更新的区间不是一个整区间 else q[o].len = q[ll].len + q[rr].len;}void build_tree(int o, int l, int r) { q[o].l = l, q[o].r = r; q[o].s = 0, q[o].len = 0; if (l == r) return; int mid = (l+r)>>1; build_tree(lson); build_tree(rson);} void updata_tree(int o, int l, int r, int val) { if (q[o].l == l and q[o].r == r) { q[o].s += val;//上边从线段树的维护中删除 下边进入 push_up(o); return; } int mid = (q[o].l+q[o].r) >> 1; if (r <= mid) updata_tree(ll, l, r, val); else if (l > mid) updata_tree(rr, l, r, val); else { updata_tree(lson, val); updata_tree(rson, val); } push_up(o);}int main(int argc, char const *argv[]){ int Kcase = 0; while (scanf("%d", &N), N) { double res = 0.0; int tot = 0; for (int i = 0; i < N; i++) { double x1, x2, y1, y2; scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); edge[tot].l = x1, edge[tot].r = x2; edge[tot].h = y1; edge[tot].f = 1; X[tot] = x1; edge[++tot].l = x1, edge[tot].r = x2; edge[tot].h = y2; edge[tot].f = -1; X[tot] = x2; tot++; } sort(edge, edge+tot, cmp); sort(X, X + tot); int k = 1; //去重 for (int i = 1; i < tot; i++) if (X[i] != X[i-1]) X[k++] = X[i]; build_tree(1, 0, k-1); for (int i = 0; i < tot; i++) { int l = lower_bound(X, X+k, edge[i].l) - X; int r = lower_bound(X, X+k, edge[i].r)-X-1; updata_tree(1, l, r, edge[i].f); res += (edge[i+1].h-edge[i].h)*q[1].len; } printf("Test case #%d\nTotal explored area: %.2f\n\n", ++Kcase, res); } return 0;}

转载于:https://www.cnblogs.com/cniwoq/p/9122736.html

你可能感兴趣的文章
[转]CMake快速入门教程:实战
查看>>
IntelliJ IDEA创建JavaWeb工程及配置Tomcat部署
查看>>
Markdown用法
查看>>
求最大值及其下标
查看>>
Request header is too large
查看>>
轮播插件swiper.js?
查看>>
网路流24题总结
查看>>
BZOJ-3732 Network 图论 最小生成树 倍增
查看>>
python之文件操作
查看>>
15 个 Android 通用流行框架大全
查看>>
Entity Framwork CodeFirst 学习笔记五:数据库映射的默认配置和设置
查看>>
ant 执行java文件,java文件中含中文,显示乱码
查看>>
IE8兼容@media和mp4视频的解决方案
查看>>
第二周总结
查看>>
ASP.NET完整打包卸载更新攻略(By Installshield 2010)
查看>>
[120_移动开发Android]006_android开发之数据存储之sdcard访问
查看>>
[若有所悟]IT小兵总结IT人特点及挽留IT人才的九大策略
查看>>
概率图模型建模、学习、推理资料总结
查看>>
【转】知道这20个正则表达式,能让你少写1,000行代码
查看>>
自定义 启动和关闭 oracle 的命令
查看>>