(线段树 + 扫描线)亚特兰蒂斯

1|0原题链接:

亚特兰蒂斯

2|0题目:

有几个古希腊书籍中包含了对传说中的亚特兰蒂斯岛的描述。

其中一些甚至包括岛屿部分地图。

但不幸的是,这些地图描述了亚特兰蒂斯的不同区域。

您的朋友 Bill 必须知道地图的总面积。

你自告奋勇写了一个计算这个总面积的程序。

输入格式
输入包含多组测试用例。

对于每组测试用例,第一行包含整数 n,表示总的地图数量。

接下来 n 行,描绘了每张地图,每行包含四个数字 x1,y1,x2,y2(不一定是整数),(x1,y1) 和 (x2,y2) 分别是地图的左上角位置和右下角位置。

注意,坐标轴 x 轴从上向下延伸,y 轴从左向右延伸。

当输入用例 n=0 时,表示输入终止,该用例无需处理。

输出格式
每组测试用例输出两行。

第一行输出 Test case #k,其中 k 是测试用例的编号,从 1 开始。

第二行输出 Total explored area: a,其中 a 是总地图面积(即此测试用例中所有矩形的面积并,注意如果一片区域被多个地图包含,则在计算总面积时只计算一次),精确到小数点后两位数。

在每个测试用例后输出一个空行。

数据范围
1≤n≤10000,
0≤x1<x2≤100000,
0≤y1<y2≤100000
注意,本题 n 的范围上限加强至 10000。

输入样例:
2
10 10 20 20
15 15 25 25.5
0
输出样例:
Test case #1
Total explored area: 180.00

样例解释
样例所示地图覆盖区域如下图所示,两个矩形区域所覆盖的总面积,即为样例的解。

3|0思路:

#include<bits/stdc++.h> using namespace std; #define endl '\n' typedef long long ll; typedef pair<int, int> PII; const int mod = 1e9 + 7; const int inf = 0x3f3f3f3f; const int N = 1e5 + 10; int n, m; unordered_map<double, int> mp; struct Segment{ double x, y1, y2; int k; bool operator < (const Segment &t) const{ return x < t.x; } }seg[N << 1]; struct Node{ int l, r; int cnt; double len; }tr[N << 3]; vector<double> ys; int find(double y){ return lower_bound(ys.begin(), ys.end(), y) - ys.begin(); } void pushup(int u){ if(tr[u].cnt) tr[u].len = ys[tr[u].r + 1] - ys[tr[u].l]; else if(tr[u].l != tr[u].r){ tr[u].len = tr[u << 1].len + tr[u << 1 | 1].len; } else tr[u].len = 0; } void build(int u, int l, int r){ tr[u] = {l, r, 0, 0}; if(l != r){ int mid = l + r >> 1; build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r); } } void modify(int u, int l, int r, int k){ if(tr[u].l >= l && tr[u].r <= r){ tr[u].cnt += k; pushup(u); } else{ int mid = tr[u].l + tr[u].r >> 1; if(l <= mid) modify(u << 1, l, r, k); if(r > mid) modify(u << 1 | 1, l, r, k); pushup(u); } } int main(void){ ios::sync_with_stdio(false); cin.tie(0); int T = 1; while(cin >> n && n){ ys.clear(); mp.clear(); for(int i = 0, j = 0; i < n; i++){ double x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; seg[j ++] = {x1, y1, y2, 1}; seg[j ++] = {x2, y1, y2, -1}; if(!mp.count(y1)) mp[y1] = 1, ys.push_back(y1); if(!mp.count(y2)) mp[y2] = 1, ys.push_back(y2); } sort(ys.begin(), ys.end()); build(1, 0, ys.size() - 2); sort(seg, seg + n * 2); double res= 0; for(int i = 0; i < n * 2; i ++){ if(i > 0) res += tr[1].len * (seg[i].x - seg[i - 1].x); modify(1, find(seg[i].y1), find(seg[i].y2) - 1, seg[i].k); } cout << "Test case #" << T++ << endl; cout << "Total explored area: " << setprecision(2) << fixed << res << endl << endl; } return 0; }

__EOF__

本文作者ReSakura
本文链接https://www.cnblogs.com/ReSakura/p/16212473.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ReSakura  阅读(89)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示