leetcode 1840. 最高建筑高度 困难

在一座城市里,你需要建 n 栋新的建筑。这些新的建筑会从 1n 编号排成一列。

这座城市对这些新建筑有一些规定:

  • 每栋建筑的高度必须是一个非负整数。
  • 第一栋建筑的高度 必须0
  • 任意两栋相邻建筑的高度差 不能超过 1

除此以外,某些建筑还有额外的最高高度限制。这些限制会以二维整数数组 restrictions 的形式给出,其中 restrictions[i] = [idi, maxHeighti] ,表示建筑 idi 的高度 不能超过 maxHeighti

题目保证每栋建筑在 restrictions至多出现一次 ,同时建筑 1 不会 出现在 restrictions 中。

请你返回 最高 建筑能达到的 最高高度

示例 1:

复制代码
输入:n = 5, restrictions = [[2,1],[4,1]]
输出:2
解释:上图中的绿色区域为每栋建筑被允许的最高高度。
我们可以使建筑高度分别为 [0,1,2,1,2] ,最高建筑的高度为 2 。

示例 2:

复制代码
输入:n = 6, restrictions = []
输出:5
解释:上图中的绿色区域为每栋建筑被允许的最高高度。
我们可以使建筑高度分别为 [0,1,2,3,4,5] ,最高建筑的高度为 5 。

示例 3:

复制代码
输入:n = 10, restrictions = [[5,3],[2,5],[7,4],[10,3]]
输出:5
解释:上图中的绿色区域为每栋建筑被允许的最高高度。
我们可以使建筑高度分别为 [0,1,2,3,3,4,4,5,4,3] ,最高建筑的高度为 5 。

提示:

  • 2 <= n <= 10^9
  • 0 <= restrictions.length <= min(n - 1, 10^5)
  • 2 <= idi <= n
  • idi唯一的
  • 0 <= maxHeighti <= 10^9

分析:这题本质是把每个 restriction 当作一个"高度上界约束点",由于相邻建筑高度差最多为 1,因此从左到右可以把每个点的高度限制为前一个点高度加上距离得到的上界,从右到左再用同样规则修正一次,从而保证所有 restriction 同时满足时的全局最优高度上界,最后答案等价于相邻 restriction 区间内由两端高度与距离共同决定的折线峰值最大值,即在满足双向约束后的最小上包络下取最大高度。

cpp 复制代码
class Solution {
public:
    int maxBuilding(int n, vector<vector<int>>& restrictions) {
        if(restrictions.empty())return n-1;
        sort(restrictions.begin(), restrictions.end());
        restrictions.insert(restrictions.begin(),{1,0});
        int m=restrictions.size();
        if(restrictions[m-1][0]!=n)restrictions.push_back({n,n-1}),m++;

        for(int i=1;i<m;i++)
        {
            int dist=restrictions[i][0]-restrictions[i-1][0];
            restrictions[i][1]=min(restrictions[i][1],restrictions[i-1][1]+dist);
        }
        for(int i=m-2;i>=0;i--)
        {
            int dist=restrictions[i+1][0]-restrictions[i][0];
            restrictions[i][1]=min(restrictions[i][1],restrictions[i+1][1]+dist);
        }
        int ret=0;
        for(int i=0;i<m-1;i++)
        {
            int x1=restrictions[i][0];
            int h1=restrictions[i][1];
            int x2=restrictions[i+1][0];
            int h2=restrictions[i+1][1];
            int dist=x2-x1;

            ret=max(ret,(h1+h2+dist)/2);
        }

        return ret;
    }
};