题目链接

题目

题目描述

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.

输入描述

The input consists of several test cases. Each test case starts with a line containing a single integer n \((1 \leq n \leq 100)\) of available maps. The n following lines describe one map each. Each of these lines contains four numbers \(x_1;y_1;x_2;y_2\) \((0 \leq x_1 \lt x_2 \leq 100000;0 \leq y_1 \lt y_2 \leq 100000)\) , not necessarily integers. The values \((x_1; y_1)\) and \((x_2;y_2)\) 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.

输出描述

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.

示例1

输入

2
10 10 20 20
15 15 25 25.5
0

输出

Test case #1
Total explored area: 180.00

题解

知识点:扫描线,线段树,离散化。

线段树+扫面线处理面积并问题,是板子题。

更新时,通过到上次更新的距离与线段覆盖长度,来计算面积。

时间复杂度 \(O(n \log n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long; template<class T>
struct Discretization {
vector<T> uniq;
Discretization() {}
Discretization(const vector<T> &src) { init(src); }
void init(const vector<T> &src) {
uniq = src;
sort(uniq.begin() + 1, uniq.end());
uniq.erase(unique(uniq.begin() + 1, uniq.end()), uniq.end());
}
int get(T x) { return lower_bound(uniq.begin() + 1, uniq.end(), x) - uniq.begin(); }
}; template<class T>
class ScanlineA {
struct Segment {
int l, r;
int cover;
T len;
}; int n;
vector<T> dot;
vector<Segment> node; void push_up(int rt) {
if (node[rt].cover) node[rt].len = dot[node[rt].r + 1] - dot[node[rt].l];
else if (node[rt].l == node[rt].r) node[rt].len = 0;
else node[rt].len = node[rt << 1].len + node[rt << 1 | 1].len;
} void update(int rt, int l, int r, int x, int y, int cover) {
if (r < x || y < l) return;
if (x <= l && r <= y) return node[rt].cover += cover, push_up(rt);
int mid = l + r >> 1;
update(rt << 1, l, mid, x, y, cover);
update(rt << 1 | 1, mid + 1, r, x, y, cover);
push_up(rt);
} public:
ScanlineA() {}
ScanlineA(const vector<T> &_dot) { init(_dot); }
void init(const vector<T> &_dot) {
assert(_dot.size() >= 2);
n = _dot.size() - 2;
dot = _dot;
node.assign(n << 2, { 0,0,0,0 });
function<void(int, int, int)> build = [&](int rt, int l, int r) {
node[rt] = { l,r,0,0 };
if (l == r) return;
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
};
build(1, 1, n);
} void update(int x, int y, int cover) { update(1, 1, n, x, y, cover); } Segment query() { return node[1]; }
};
/// 面积并扫描线特化线段树,O(logn),配合离散化可以处理任意精度覆盖长度并问题
/// 求面积并,O(nlogn),面积并 = sum(两次扫描的距离*覆盖长度并)
//* 其中n代表线段数,并非端点数,端点数应为n+1
//* 端点编号从1开始,线段编号也从1开始
//* 任何区间(如l,r或x,y)都代表线段编号而非端点编号,即表示dot[l]到dot[r + 1],使用时注意 template<class T>
struct pk {
T val;
friend bool operator<(const pk &a, const pk &b) {
if (abs(a.val - b.val) < 1e-6) return false;//! 浮点型注意相等条件
return a.val < b.val;
}
friend bool operator==(const pk &a, const pk &b) { return !(a < b) && !(b < a); }
};
//* 专门处理浮点型比较判断的封装类 template<class T>
struct edge {
T x;
pk<T> y1, y2;
int rky1, rky2;
int flag;
}; int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
int cnt = 0;
cout << fixed << setprecision(2);
while (cnt++, cin >> n, n) {
if (cnt > 1) cout << '\n';
vector<edge<double>> e(2 * n + 1);
vector<pk<double>> y_src(2 * n + 1);
for (int i = 1;i <= n;i++) {
double x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
e[2 * i - 1] = { x1,{y1},{y2},0,0,1 };
e[2 * i] = { x2,{y1},{y2},0,0,-1 };
y_src[2 * i - 1] = { y1 };
y_src[2 * i] = { y2 };
} Discretization<pk<double>> dc(y_src);
for (int i = 1;i <= n;i++) {
e[2 * i - 1].rky1 = dc.get({ e[2 * i - 1].y1 });
e[2 * i - 1].rky2 = dc.get({ e[2 * i - 1].y2 });
e[2 * i].rky1 = dc.get({ e[2 * i].y1 });
e[2 * i].rky2 = dc.get({ e[2 * i].y2 });
}
sort(e.begin() + 1, e.end(), [&](const auto &a, const auto &b) {return a.x < b.x;}); vector<double> dot(dc.uniq.size());
for (int i = 1;i < dot.size();i++) dot[i] = dc.uniq[i].val;
ScanlineA<double> sla(dot);
double ans = 0;
sla.update(e[1].rky1, e[1].rky2 - 1, e[1].flag);
for (int i = 2;i <= 2 * n;i++) {
ans += (e[i].x - e[i - 1].x) * sla.query().len;
sla.update(e[i].rky1, e[i].rky2 - 1, e[i].flag);
}
cout << "Test case #" << cnt << '\n';
cout << "Total explored area: " << ans << '\n';
}
return 0;
}
/*
2
10 10 20 20
15 15 25 25.5
2
10 10 20 20
15 15 25 25.5
0 Test case #1
Total explored area: 180.00 Test case #2
Total explored area: 180.00
*/

NC51111 Atlantis的更多相关文章

  1. [POJ1151]Atlantis

    [POJ1151]Atlantis 试题描述 There are several ancient Greek texts that contain descriptions of the fabled ...

  2. 线段树---Atlantis

    题目网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110064#problem/A Description There are se ...

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

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

  4. 【POJ】1151 Atlantis(线段树)

    http://poj.org/problem?id=1151 经典矩形面积并吧.....很简单我就不说了... 有个很神的地方,我脑残没想到: 将线段变成点啊QAQ这样方便计算了啊 还有个很坑的地方, ...

  5. HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

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

  6. POJ 1542 Atlantis(线段树 面积 并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 参考网址:http://blog.csdn.net/sunmenggmail/article/d ...

  7. [POJ 1151] Atlantis

    一样的题:HDU 1542 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18148   Accepted ...

  8. 【HDU 1542】Atlantis 矩形面积并(线段树,扫描法)

    [题目] Atlantis Problem Description There are several ancient Greek texts that contain descriptions of ...

  9. 【POJ1151】【扫描线+线段树】Atlantis

    Description There are several ancient Greek texts that contain descriptions of the fabled island Atl ...

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

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

随机推荐

  1. Seata 分布式事务解决方案及特点

    本文为博主原创,未经允许不得转载: 目录: 1. Seata官方链接 2. Seata的三大角色 3.Seata 常见分布式事务解决方案 4. 2PC两阶段提交协议 5. 2PC 的问题 6. AT模 ...

  2. 分享这位大神的WPF界面设计系列视频

    本文结构: 前言 视频详情 搬运详情 总结 4.1 国内推荐WPF资源 4.2 B站是学习的天堂 4.3 去外面看看 4.4 个人给C/S同学建议 1. 前言 今天介绍油管上一个大佬发的WPF设计系列 ...

  3. P1914 小书童——凯撒密码

    1.题目介绍 小书童--凯撒密码 题目背景 某蒟蒻迷上了 "小书童",有一天登陆时忘记密码了(他没绑定邮箱 or 手机),于是便把问题抛给了神犇你. 题目描述 蒟蒻虽然忘记密码,但 ...

  4. [转帖]Kubernetes 1.23:IPv4/IPv6 双协议栈网络达到 GA

    https://kubernetes.io/zh-cn/blog/2021/12/08/dual-stack-networking-ga/#:~:text=Kubernetes%201.23%EF%B ...

  5. [转帖]linux之iftop命令

    https://rumenz.com/rumenbiji/linux-iftop.html Linux安装iftop > yum install iftop -y > iftop 界面如下 ...

  6. [转帖]谈谈对K8S CNI、CRI和CSI插件的理解

    K8S的设计初衷就是支持可插拔架构,解决PaaS平台不好用.不能用.需要定制化等问题,K8S集成了插件.附加组件.服务和接口来扩展平台的核心功能.附加组件被定义为与环境的其他部分无缝集成的组件,提供类 ...

  7. React中函数组件与类组件的两种使用

    React 创建组件的两种方式 函数组件:使用js函数创建的组件 约定1:函数名称必须以大写字母开头 约定2:函数组件必须要有返回值. 如果返回值为null.表示不渲染任何内容. return nul ...

  8. 【代码分享】使用 terraform, 在 Let's Encrypt 上申请托管在 cloudflare 上的域名对应的证书

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 运行的流程可以抽象为上图. 直接贴代码: letsencr ...

  9. 【记录一个问题】vm-select和vm-storage均无法做并行查询

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 看我提的这个issue: need parallel qu ...

  10. 【JS 逆向百例】网洛者反爬练习平台第三题:AAEncode 加密

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...