• 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;
        }
    };
    
  • 相关阅读:
    160309_Qt Essentials
    160309_Qt Reference Documentation
    160308_Signals & Slots
    160308_Helloworld_Gui Application
    网络爬虫(14)-动态页面爬取
    数据分析(6)-Pandas日期数据处理
    mysql基础(2)-excel功能在excel中如何实现?
    数据分析(5)-数据可视化常用图表类型和使用场景
    财经数据(6)-Python多进程爬虫东方财富个股盘口异动数据
    财经数据(5)-开盘啦股票标签数据爬虫
  • 原文地址:https://www.cnblogs.com/wdt1/p/13881517.html
Copyright © 2020-2023  润新知