洛谷题单指南-前缀和差分与离散化-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;
}

 

posted @ 2024-08-05 23:13  五月江城  阅读(25)  评论(0编辑  收藏  举报