我们将数组分为 left 和 right
两部分,只要能保证左右两段分别是漂亮数组,且不存在 \(A[k]*2=A[i]+A[j]\)(其中 \(A[i],A[j]\) 分别属于 left 和
right),那么整个数组就是一个漂亮数组。我们发现等式右边是个偶数,那么只需要让
left 中都是奇数,right
中都是偶数,就可以满足条件。
每个建筑物的几何信息用三元组 [Li,Ri,Hi] 表示,其中 Li 和 Ri
分别是第 i 座建筑物左右边缘的 x 坐标,Hi 是其高度。可以保证 0 ≤ Li, Ri ≤
INT_MAX, 0 < Hi ≤ INT_MAX 和 Ri - Li >
0。您可以假设所有建筑物都是在绝对平坦且高度为 0 的表面上的完美矩形。
由于输入是按 Li 升序排序的,我们可以递归地将建筑物按
Li
分为两部分,分别求出左右两段独立的天际线,然后设法将其合并成一条。当划分到只有一座建筑物的时候,返回
[[Li, Hi], [Ri, 0]] 即可。
合并的过程类似于归并排序,我们用两个指针分别指向左右两段当前的点,将
x 坐标更小的先加入结果列表。而对于 y
坐标,还应考虑另一段中最后一个进入结果列表的点的高度,取其与自身高度之间的最大值。此外,在加入结果列表之前,要先与列表最后一个点的高度作比较,如果高度相同,则说明在一条水平线上,应舍弃后一个点。
vector<vector<int>> getSubSkyline(vector<vector<int>> &buildings, int lo, int hi) { if (lo == hi) { return {{buildings[lo][0], buildings[lo][2]}, {buildings[lo][1], 0}}; }
int mid = lo + ((hi - lo) >> 1); vector<vector<int>> left = getSubSkyline(buildings, lo, mid); vector<vector<int>> right = getSubSkyline(buildings, mid + 1, hi);
int lh_prev = 0, rh_prev = 0; int i = 0, j = 0; vector<int> temp; vector<vector<int>> res; while (i < left.size() && j < right.size()) { if (left[i][0] < right[j][0]) { temp = {left[i][0], max(left[i][1], rh_prev)}; lh_prev = left[i++][1]; } elseif (left[i][0] > right[j][0]) { temp = {right[j][0], max(right[j][1], lh_prev)}; rh_prev = right[j++][1]; } else { temp = {left[i][0], max(left[i][1], right[j][1])}; lh_prev = left[i++][1]; rh_prev = right[j++][1]; } if (res.size() == 0 || res[res.size()-1][1] != temp[1]) { res.push_back(temp); } } while (i < left.size()) res.push_back(left[i++]); while (j < right.size()) res.push_back(right[j++]); return res; } };