洛谷题单指南-前缀和差分与离散化-P1904 天际线
原题链接:https://www.luogu.com.cn/problem/P1904
题意解读:给出(左端点,高度,右端点)表示的若干建筑,要输出其轮廓,所谓轮廓就是每个点被覆盖的最高建筑的高度所描绘的线。
解题思路:
如果能计算每个点被覆盖的最高建筑的高度,用数组h[10005]保存,那么输出轮廓的过程只需要枚举每一个点,如果点的高度和前一个点不同,则输出该点的坐标和高度,即可得到答案。
问题变成,如何计算每个点被覆盖的最高建筑的高度?
由于同一个点可能有多个建筑覆盖,因此可以将建筑按照左端点从小到大排序,
枚举1-10000每一个坐标i
取出左端点最小的建筑,如果有多个左端点相同的建筑,则取出所有,取高度最大的那个maxh,记录h[i] = maxh
已经计算过的坐标可以从建筑中移除,也就是将左端点坐标+1,直到左端点等于右端点
由于要实现每次对建筑左端点坐标+1,再枚举下一个坐标时依然要取左端点最小的建筑,可以借助于优先队列
建筑表示为struct node {int l, h, r},
优先队列按l小的在堆顶
struct node
{
int l, h, r;
bool operator < (const node &a) const
{
return l > a.l;
}
};
100分代码:
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l, h, r;
bool operator < (const node &a) const
{
return l > a.l;
}
};
priority_queue<node> q;
int high[10005]; //每个点对应的最高建筑高度
int main()
{
int l, h, r;
while(cin >> l >> h >> r)
{
q.push({l, h, r});
}
for(int i = 1; i <= 10000; i++)
{
int maxh = 0;
while(q.size() && q.top().l == i)
{
node tmp = q.top();
maxh = max(maxh, tmp.h);
q.pop();
if(++tmp.l != tmp.r) q.push(tmp);
}
high[i] = maxh;
}
for(int i = 1; i <= 10000; i++)
{
if(high[i] != high[i - 1])
{
cout << i << " " << high[i] << " ";
}
}
return 0;
}