the skyline problem(line sweep)

A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skylineformed by these buildings collectively (Figure B).

Buildings Skyline Contour

The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.

For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] .

 

/* 在轮廓上进行遍历 pre cur 分别为之前和当前的最高高度 最高高度发生变化时即是拐点(用一根平行x的直线进行line sweep)
 * 扫描时如果是左边界 入队 如果是右边界就删除 同时和之前的高度比较
 * 扫描顺序!!重要
 *   1.按x从小到大扫描
 *   2. 如果x值相同 若是在上升扫描(即左边界 )要先扫描到高的位置(不然低的先进入会多一个拐点)
 *                     在右边界时 先扫描低的位置 (不然高的位置先出队 会多一个拐点)
 *                     左边界比右边界优先入队 (插入先于删除)
 *    发现如果把左边界设为负数 2的条件都能满足
 * 构建一个最大堆 排序方法为: 按x从大到小 若x相同 且是左边界 y值小的在上面  右边界
 *
 * */
class Solution {
public:
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
        vector<vector<int>> ret;
        multiset<int> s; // 基于红黑树的 根节点的值最小 begin()返回第一个节点即最小值  rbegin()返回最后一个节点即最大值
        vector<pair<int, int>> tmp; // 存放x 及对应的高度
        for(auto &b : buildings){
            tmp.emplace_back(b[0], -b[2]);
            tmp.emplace_back(b[1], b[2]);
        }
        sort(tmp.begin(), tmp.end());
        // 开始扫描 每次左边界入set 右边界从set中删除 最高高度变化即为拐点
        int pre=0, cur=0;
        //cout<<tmp[0].first;
        s.insert(0);
        for(auto & v:tmp){
            if(v.second<0)  s.insert(-v.second);
            else s.erase(s.find(v.second));// multiset 不能erase(val)会删除所有的 只要找到一个删除就好
            cur = *s.rbegin();
            if(cur != pre){
                ret.push_back({v.first, cur});
                pre = cur;
            }
        }
        return ret;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值