LeetCode 218. The Skyline Problem(線段樹+離散化)

題目

題意:就是有一些矩形,然後讓你輸出一些點,這些點連成的線是這些矩形的外圍。叫做城市天際線。具體的看題目就好了。

題解:首先,設立一個區間,用數組表示。每遇到一個矩形,我們就把這個矩形的底部的寬所佔的區間的值全部都設成這個矩形的高。在覆蓋區間的時候,如果發現這個區間已經被覆蓋過,如果當前值比原有值低,就不覆蓋了,比原有值高採取覆蓋。一開始的區間的長度當然是0,相當於這個城市都是平地。當我們把所有矩形都覆蓋之後,把區間的長度當做寬,當做高,就是上面圖片中的第二張。然後那些點,怎麼確定呢?其實就是從區間的最左邊開始,遇到第一個值發生變化的那個點,是我們需要的,然後從這個點再向右找,找到區間值又發生變化的下一個點。以此循環,直到發現某個點向右的值都沒有變化了,就停止了。

那上面一系列操作,最合適的數據結構就是線段樹了,可以滿足的我們的需求。覆蓋點,以及找到某個點開始,第一個值發生變化的點。

但是題目的數據範圍是0-INTMAX,直接建立線段樹會炸的,所以我們必須要離散化!

typedef long long int _int;
class Solution {
public:
    int num[500005];
    int height;
    map<_int,int> m;
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {

        vector<vector<int>> ans;
        if(buildings.size()==0)
            return ans;

        memset(num,0,sizeof(num));

        vector<_int> a;
        for(int i=0;i<buildings.size();i++)
        {
            a.push_back(buildings[i][0]);
            a.push_back(buildings[i][1]);
            a.push_back((_int)buildings[i][1]+1);
        }

        sort(a.begin(),a.end());

        int pos=0;
        vector<_int> b;
        for(int i=0;i<a.size();i++)
        {
            if(m[a[i]]==0)
            {
                m[a[i]] = ++pos;
                b.push_back(a[i]);
            }
        }

        int last;
        for(int i=0;i<buildings.size();i++)
        {
            update(1,1,pos+2,m[buildings[i][0]],m[buildings[i][1]],buildings[i][2]);
        }

        _int start=1;
        height = 0;
        int pre = height;

        while(1)
        {
            pre = height;

            start = query(1,1,pos+2,start,height);

            if(start==-1)
            {
                break;
            }

            vector<int> res;
            if(height < pre)
                res.push_back(b[start-1]-1);
            else
                res.push_back(b[start-1]);

            res.push_back(height);

            ans.push_back(res);
        }
        return ans;


    }

    void pushup(int node)
    {
        if(num[node<<1]==num[node<<1|1])
            num[node]=num[node<<1];
        else
            num[node]=-1;
    }

    void pushdown(int node)
    {
        if(num[node]!=-1)
        {
            num[node<<1]=num[node];
            num[node<<1|1]=num[node];
        }
    }


    void update(int node,_int l,_int r,_int start,_int end,int val)
    {
        if(start<=l&&r<=end)
        {
            if(num[node]!=-1)
            {
                if(num[node]<val)
                    num[node]=val;

                return;
            }

        }
        pushdown(node);

        _int mid = (l+r)>>1;
        if(start<=mid)
            update(node<<1,l,mid,start,end,val);
        if(end >mid)
            update(node<<1|1,mid+1,r,start,end,val);

        pushup(node);
    }

    int query(int node,_int l,_int r,_int start,_int val)
    {
        if(num[node]!=-1)
        {
            if(num[node]==val)
                return -1;
            else
            {
                height = num[node];
                return l;
            }
        }
        pushdown(node);

        _int mid = (l+r)>>1;
        int res;
        if(start<=mid)
        {
            res = query(node<<1,l,mid,start,val);
            if(res!=-1)
                return res;
        }

        res = query(node<<1|1,mid+1,r,start,val);

        pushup(node);

        return res;
    }


};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章