1. 程式人生 > 實用技巧 >100天際線問題(218)

100天際線問題(218)

作者: Turbo時間限制: 1S章節: 線段樹

晚於: 2020-09-09 12:00:00後提交分數乘係數50%

問題描述 :

城市的天際線是從遠處觀看該城市中所有建築物形成的輪廓的外部輪廓。現在,假設您獲得了城市風光照片(圖A)上顯示的所有建築物的位置和高度,請編寫一個程式以輸出由這些建築物形成的天際線(圖B)。

每個建築物的幾何資訊用三元組 [Li,Ri,Hi] 表示,其中 Li 和 Ri 分別是第 i 座建築物左右邊緣的 x 座標,Hi 是其高度。可以保證 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX 和 Ri - Li > 0。您可以假設所有建築物都是在絕對平坦且高度為 0 的表面上的完美矩形。

例如,圖A中所有建築物的尺寸記錄為:[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] 。

輸出是以 [ [x1,y1], [x2, y2], [x3, y3], ... ] 格式的“關鍵點”(圖B中的紅點)的列表,它們唯一地定義了天際線。關鍵點是水平線段的左端點。請注意,最右側建築物的最後一個關鍵點僅用於標記天際線的終點,並始終為零高度。此外,任何兩個相鄰建築物之間的地面都應被視為天際線輪廓的一部分。

例如,圖B中的天際線應該表示為:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]。

輸入說明 :

首先輸入建築物的數量n

然後輸入n行,每行是一座建築物的幾何資訊三元組 [Li,Ri,Hi]

n在 [0, 10000] 範圍內

建築物列表按照Li的x 座標進行升序排列輸入

輸出說明 :

輸出天際線表示,每個關鍵點一行,每行兩個整數。

輸出列表必須按關鍵點的 x座標升序排列輸出。

輸出天際線中不得有連續的相同高度的水平線。例如 [...[2 3], [4 5], [7 5], [11 5], [12 7]...] 是不正確的答案;三條高度為 5 的線應該在最終輸出中合併為一個:[...[2 3], [4 5], [12 7], ...]

輸入範例 :

輸出範例 :

#include <iostream>
#include <vector>
#include <set>
using namespace std;
class Solution {
public:
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
        multiset<pair<int, int>> s;
        vector<vector<int>> res;
        
        for (auto& temp : buildings) 
        {
            s.insert(make_pair(temp[0], -temp[2])); // 左端點,高度入集合
            s.insert(make_pair(temp[1], temp[2])); // 右端點,高度入集合 
        }
        
        multiset<int> heights({0}); // 儲存當前位置所有高度。
        vector<int> last = {0, 0}; // 儲存上一個位置的橫座標以及高度
        for (auto& i : s) 
        {
            if (i.second < 0) heights.insert(-i.second); // 左端點,高度入堆
            else heights.erase(heights.find(i.second)); // 右端點,移除高度
            
            // 當前關鍵點,最大高度
            auto maxHeight = *heights.rbegin();
            
            // 當前最大高度如果不同於上一個高度,說明這是一個轉折點
            if (last[1] != maxHeight) 
            {
                // 更新 last,並加入結果集
                last[0] = i.first;
                last[1] = maxHeight;
                res.push_back(last);
            }
        }
        
        return res;
    }
};

int main()
{
    int n,m;
    cin>>n;
    vector<vector<int>> buildings;
    for(int i=0;i<n;i++)
    {
        vector<int> row;
        for(int j=0;j<3;j++)
        {
            cin>>m;
            row.push_back(m);
        }
        buildings.push_back(row);
    }
    vector<vector<int>> res=Solution().getSkyline(buildings);
    for(int i=0;i<res.size();i++)
    {
        for(int j=0;j<2;j++)
        {
            if(j>0)
                cout<<" ";
            cout<<res[i][j];
        }
        if(i!=res.size()-1)
            cout<<endl;
    }
}
//mulset用法:https://blog.csdn.net/sodacoco/article/details/84798621