美丽塔2

给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。

你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i ,高度为 heights[i] 。

如果以下条件满足,我们称这些塔是 美丽 的:

1 <= heights[i] <= maxHeights[i]
heights 是一个 山状 数组。
如果存在下标 i 满足以下条件,那么我们称数组 heights 是一个 山状 数组:

对于所有 0 < j <= i ,都有 heights[j - 1] <= heights[j]
对于所有 i <= k < n - 1 ,都有 heights[k + 1] <= heights[k]
请你返回满足 美丽塔 要求的方案中,高度和的最大值 。

示例 1:

输入:maxHeights = [5,3,4,1,1]
输出:13
解释:和最大的美丽塔方案为 heights = [5,3,3,1,1] ,这是一个美丽塔方案,因为:

  • 1 <= heights[i] <= maxHeights[i]
  • heights 是个山状数组,峰值在 i = 0 处。
    13 是所有美丽塔方案中的最大高度和。
    示例 2:

输入:maxHeights = [6,5,3,9,2,7]
输出:22
解释: 和最大的美丽塔方案为 heights = [3,3,3,9,2,2] ,这是一个美丽塔方案,因为:

  • 1 <= heights[i] <= maxHeights[i]
  • heights 是个山状数组,峰值在 i = 3 处。
    22 是所有美丽塔方案中的最大高度和。
    示例 3:

输入:maxHeights = [3,2,5,5,2,3]
输出:18
解释:和最大的美丽塔方案为 heights = [2,2,5,5,2,2] ,这是一个美丽塔方案,因为:

  • 1 <= heights[i] <= maxHeights[i]
  • heights 是个山状数组,最大值在 i = 2 处。
    注意,在这个方案中,i = 3 也是一个峰值。
    18 是所有美丽塔方案中的最大高度和。

提示:

1<=n==maxHeights<=1051<=maxHeights[i]<=109

解题思路

见代码注释

code

typedef long long int LL;

class Solution {
public:
    //朴素解法:遍历两侧的递减序列并求和
    //O(n ^ 2)
    
    //预处理两侧递减序列的和并且在枚举的可以直接查询
    //关键:如何在O(n)的时间内预处理出两侧递减序列的和
    //6 5 3 9 2 7
    //i -> n-1的递减序列的和
    //直接找到所有的递减序列再求和是否可以
    //6 5 3 3 2 2
    //显然是不可以的
    //要查找i -> n-1 的递减序列必须从后先前遍历
    //如果使用朴素的解法是O(n ^ 2)的需要根据当前的数值更新后面的结果
    //实际上从后向前维护的就是一个单调栈
    //在维护单调栈的过程中记录序列和
    //7
    //2 2
    //9 2 2
    //....
    //如何求序列和
    //相同的只记录最左边的index
    //个数可以通过index之间的差值计算
    //出栈就是减去个数 * value
    //入栈就是加上个数 * value
    //可以实现在O(1)的时间更新序列和不需要遍历整个stack中元素求和
    
    //前面同理

    long long maximumSumOfHeights(vector<int>& maxHeights) {
        LL ans = 0;
        stack<int> st1;
        int len = maxHeights.size();
        st1.push(len);
        vector<LL> suffix(len + 1,0);
        for(int i = len - 1;i >= 0;i --)
        {
            suffix[i] = suffix[i + 1];
            while(st1.size() > 1 && maxHeights[i] <= maxHeights[st1.top()]) 
            {
                int idx = st1.top();
                st1.pop();
                suffix[i] -= (st1.top() - (LL)idx) * (LL)maxHeights[idx];
            }
            suffix[i] += (st1.top() - (LL)i) * (LL)maxHeights[i];
            st1.push(i);
        }

        //for(int i = 0;i < len;i ++) cout<<suffix[i]<<" ";
        //cout<<endl;

        stack<int> st2;
        vector<LL> pre(len,0);
        st2.push(-1);

        for(int i = 0;i < len;i ++)
        {
            if(i != 0) pre[i] = pre[i - 1];
            while(st2.size() > 1 && maxHeights[i] <= maxHeights[st2.top()])
            {
                int idx = st2.top();
                st2.pop();
                pre[i] -= (idx - (LL)st2.top()) * (LL)maxHeights[idx];
            }
            pre[i] += (i - (LL)st2.top()) * (LL)maxHeights[i];
            st2.push(i);
        }
        //for(int i = 0;i < len;i ++) cout<<pre[i]<<" ";

        for(int i = 0;i < len;i ++) ans = max<LL>(ans,pre[i] + suffix[i] - maxHeights[i]);
        return ans;    
    }
};
posted on   huangxk23  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示