1. 程式人生 > 實用技巧 >218. The Skyline Problem

218. The Skyline Problem

問題:

給定一個數組,表示樓的寬+高[x1,x2,h],求所形成的城市輪廓。

Input
[[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
Output
[[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]

Input
[[1,2,1],[1,2,2],[1,2,3]]
Output
[[1,3],[2,0]]

  

解法:

解法一:FenwickTree

利用特點:通常的FenwickTree(如下圖)所求為,前0~i個元素的和。

前面的值 貢獻構成->後面的值

這裡,我們利用字尾構造,求第i~∞個元素中的最大值。

後面的值(x2) 貢獻構成->前面的值(x1~x2之間的值)。

  • index:x2
  • value:max(h)

例如,上圖中

  • tree[2]:表示node[2]的最大值和node[3]的最大值,再求最大值。
  • tree[8]:表示node[8],node[9]...node[15]的最大值。

在本問題中,我們每讀入一個樓的資訊(遍歷到x1的位置時),[x1,x2,h] 將上述的資料結構 update(x2, h)

更新node[x2]上的值,同時更新<x2的idx上的各個node的值。

  • 當我們求,x0的最大值時,還未錄入h,x0累計>x0的各個值。由於剛開始所以都為0
  • 當我們求,x1.5的最大值時,已錄入h,x1.5累計>x1.5的各個值,包含x2。因此為h
  • 當我們求,x3的最大值時,x3累計>x3的各個值,不包含x2,因此h不能參與計算。
程式碼參考:
 1 class FenwickTree {//Suffix sum tree (Normal is Preffix sum tree)
 2 public:
 3     FenwickTree(int n):tree(n+1, 0) {}
 4     void update(int i, int delta) {
 5         i++;
 6         while(i>=1){
 7             tree[i]=max(tree[i], delta);
8 i -= lowbit(i); 9 } 10 } 11 int getSuMax(int i) {//max(i~infinite) 12 int maxres = 0; 13 i++; 14 while(i<tree.size()){ 15 maxres=max(tree[i], maxres); 16 i += lowbit(i); 17 } 18 return maxres; 19 } 20 21 private: 22 vector<int> tree; 23 int lowbit(int x) { 24 return x&(-x); 25 } 26 }; 27 28 class Event { 29 public: 30 int x;//座標x 31 int h;//高度 32 int i;//樓號 33 }; 34 35 class Solution { 36 public: 37 static bool cmp(Event a, Event b){ 38 return (a.x == b.x)? a.h > b.h : a.x < b.x;//x座標相同的情況下,高的排前面(防止二重輸出) 39 } 40 vector<vector<int>> getSkyline(vector<vector<int>>& buildings) { 41 set<vector<int>> res; 42 vector<Event> eventlist; 43 map<int,int> posX;//對映x2排序後的index 44 int i=0, j=0; 45 for(vector<int> b:buildings){ 46 eventlist.push_back({b[0], b[2], j});//樓開始 47 eventlist.push_back({b[1], -b[2], j++});//樓結束 48 } 49 sort(eventlist.begin(), eventlist.end(), cmp); 50 for(int i=0; i<eventlist.size(); i++){ 51 posX.insert({eventlist[i].x, i}); 52 } 53 FenwickTree ftree(eventlist.size()); 54 for(Event e:eventlist){ 55 int maxh = ftree.getSuMax(posX[e.x]);//FenwickTree query 56 if(e.h > 0) { 57 int x2 = buildings[e.i][1]; 58 ftree.update(posX[x2], e.h);//FenwickTree update 59 if(abs(e.h) > maxh) res.insert({e.x, e.h}); 60 } else { 61 int maxh2 = ftree.getSuMax(posX[e.x]+1); 62 if(abs(e.h) > maxh2) res.insert({e.x, maxh2}); 63 } 64 } 65 vector<vector<int>> res1(res.begin(), res.end());//去重 66 return res1; 67 } 68 };