大楼轮廓问题
题目描述
给定一个 N × 3 N \times 3 N×3的矩阵matrix,对于每一个长度为3的小数组arr,都表示一个大楼的三个数据。arr[0]表示大楼的左边界,arr[1]表示大楼的右边界,arr[2]表示大楼的高度(一定大于0)。每座大楼的地基都在X轴上,大楼之间可能会有重叠,请返回整体的轮廓线数组
[要求]
时间复杂度为 O ( n log n ) O(n \log n) O(nlogn)
输入描述:
第一行一个整数N,表示大楼的数量。
接下来N行,每个三个整数,表示第i个大楼的信息
输出描述:
输出若干行,每行有3个整数,表示最终的轮廓线。
示例1
输入
8
2 5 6
1 7 4
4 6 7
3 6 5
10 13 2
9 11 3
12 14 4
10 12 5
输出
1 2 4
2 4 6
4 6 7
6 7 4
9 10 3
10 12 5
12 14 4
说明

备注:
1
⩽
N
⩽
1
0
5
1 \leqslant N \leqslant 10^5
1⩽N⩽105
1
⩽
a
r
r
0
/
1
/
2
⩽
1
0
9
1 \leqslant arr_{0/1/2} \leqslant 10^9
1⩽arr0/1/2⩽109
题解:
扫描线法。
此题有一些小技巧:
- 将建筑物拆分成左右两端,分别为 {l, -h}, {r, h};
- 利用 multiset 自动排序功能,可方便取得最值。
关键思想:高度发生变化时,会产生关键点。
对拆分后的数组排序,按照以下规则:
* 若坐标相等,按照高度从小到大排序;
* 若坐标不等,按照坐标从小到大排序;
在排序后,使用一个 multiset 记录每个建筑物起始高度(负数)。从左往右扫描,如果遇到左端点,将高度入堆,如果遇到右端点,则将高度从堆中删除。如果当前高度集合中的最大高度不等于前面的最大高度,说明产生了高度变化,也就是出现了关键点,记录一下即可。
代码:
#include <cstdio>
#include <set>
#include <cctype>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int, int> PII;
void solve() {
int n;
scanf("%d", &n);
n <<= 1;
vector<PII> build( n );
int l, r, h;
for ( int i = 0; i < n; i += 2 ) {
scanf("%d%d%d", &l, &r, &h);
build[i] = {l, -h};
build[i + 1] = {r, h};
}
sort( build.begin(), build.end() );
multiset<int> heap;
heap.insert( 0 );
int prev = 0, cur = 0;
int pre_point = -1;
for ( auto &it : build ) {
if ( it.second < 0 ) heap.insert( -it.second );
else heap.erase( heap.find( it.second ) );
cur = *heap.rbegin();
if ( cur != prev ) {
if ( pre_point != -1 && prev )
printf("%d %d %d\n", pre_point, it.first, prev );
prev = cur;
pre_point = it.first;
}
}
}
int main( void ) {
solve();
return 0;
}
```
2238

被折叠的 条评论
为什么被折叠?



