zoukankan      html  css  js  c++  java
  • b_51_面积最大的矩形=柱状图 & 好子数组的最大值(暴力 / 单调栈优化)

    面积最大的矩形(柱状图)

    有一个正整数的数组(数组值为柱子的高度),化为直方图,求此直方图包含的最大矩形面积。

    暴力

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=5e5+5;
    ll n,a[N];
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n; for (int i=0; i<n; i++) cin>>a[i];
        ll ans=0;
        for (int i=1; i<n-1; i++) {
            ll l, r;
            for (l=i-1; l>=0; l--)if (a[l]<a[i]) break; //在左边找第一个小于a[i]的
            for (r=i+1; r<n; r++) if (a[r]<a[i]) break; //在右边找第一个小于a[i]的
            ans=max(ans, (r-l-1)*a[i]);    
        }
        cout<<ans;
        return 0;
    }
    

    暴力法中我发现需要在每一个位置i的左&右找第一个小于当前元素a[i]的位置,这一步可以用单调栈预处理,栈顶则存的是当前位置左/右边第一个小于自己的位置

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=5e5+5;
    ll n,h[N],l[N],r[N];
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        ll ans=0; stack<int> st;
        cin>>n; for (int i=1; i<=n; i++) cin>>h[i];
        h[0]=-1, st.push(0);           //添加一个0后最左边的柱子就可以有底部长度为1(自己本身)
        for (int i=1; i<=n; i++) {
            while (!st.empty() && h[st.top()]>=h[i]) st.pop();
            l[i]=i-st.top();
            st.push(i);
        }   
        st=stack<int>(), st.push(n+1); //添加一个n+1后最右边的柱子就可以有底部长度为1(自己本身)
        for (int i=n; i>=1; i--) {
            while (!st.empty() && h[st.top()]>=h[i]) st.pop();
            r[i]=st.top()-i;
            st.push(i);
        }   
        for (int i=1; i<=n; i++) ans=max(ans, h[i]*(l[i]+r[i]-1));
        cout<<ans;
        return 0;
    }
    

    好子数组的最大分数

    子数组 (i, j) 的 分数 定义为 min(nums[i], nums[i+1], ..., nums[j]) * (j - i + 1) 。一个 好 子数组的两个端点下标需要满足 i <= k <= j 。请你返回 好 子数组的最大可能 分数 。

    思路:单调栈O(n)求出lmin、rmin(左、右边第一个比自己小的位置),加个判断条件即可

    class Solution {
    public:
        int maximumScore(vector<int>& A, int k) {
            int n=A.size();
            A.insert(A.begin(), 0), A.insert(A.end(), 0);
            vector<int> lm(n+1,0), rm(n+1,0);
            stack<int> st; st.push(0);
            for (int i=1; i<=n; i++) {
                while (!st.empty() && A[st.top()] >= A[i]) st.pop();
                lm[i]=st.top();
                st.push(i);
            }
            st=stack<int>(); st.push(n+1);
            for (int i=n; i; i--) {
                while (!st.empty() && A[st.top()] >= A[i]) st.pop();
                rm[i]=st.top();
                st.push(i);
            }
            k++;
            int ans=0;
            for (int i=1; i<=n; i++) {
                if (lm[i] < k && k < rm[i]) 
                    ans=max(ans, (rm[i]-lm[i]-1) * A[i]);
            }
            return ans;
        }
    };
    
  • 相关阅读:
    python基础练习题(题目 矩阵对角线之和)
    python基础练习题(题目 对10个数进行排序)
    python基础练习题(题目 文本颜色设置)
    windows批处理执行图片爬取脚本
    Linux 设置网卡最大传输单位MTU
    Linux 查看开机 log
    Linux实现脚本开机自启动
    查看 linux flash 分区大小查看 linux flash 分区大小
    kernel 编译提示 mkimage command not found – U-Boot images will not be built
    linux内核编译中No rule to make ... ipt_ecn.c 的处理
  • 原文地址:https://www.cnblogs.com/wdt1/p/13881517.html
Copyright © 2011-2022 走看看