力扣第 240 场周赛 5752. 子数组最小乘积的最大值(前缀和+单调栈)

本文介绍了解决LeetCode上5752题的一种高效算法。通过使用单调栈模型来寻找每个元素作为子数组最小值时能构成的最大权值子数组,并利用前缀和快速计算子数组的总和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接

5752. 子数组最小乘积的最大值

题目大意:

给一个数组,求所有子数组的权值最大值,权值的计算方式:子数组中最小的元素乘子数组所有元素的和。

思路

一个单调栈模型的应用。如果枚举所有子数组的话那一定会超时,所以我们只能枚举每一个数,将这个数作为子数组中最小的元素,然后为了使权值最大,就得使元素的和最大,而每个元素都是正数,所以元素的数量要最大。因此对于第i个数作为最小值时,往左找最近的小于他的数,再往右找最近的小于他的数,这个区间内的数组就是满足i作为最小值的最大权值数组,然后计算每个i的数组的权值,求max即可。
看到这个往左找最近的比他小的数,就想到了单调栈。直接用单调栈模型来求即可。求子数组的和可以直接用前缀和

ac代码:

class Solution {
public:
    int maxSumMinProduct(vector<int>& nums) {
        const int N = 100010;
        typedef long long LL;
        stack<int> q;	//单调栈
        int n = 0,h[N],l[N],r[N];	//h是数组的值,l是往左找最近的小于h[i]的那个数的位置,r是往右找
        LL res = 0,sum[N];	//sum前缀和
        for(auto i : nums)
            h[++n] = i,sum[n] = sum[n-1]+i;	//把num数组转存到h来,sum求前缀和
        h[0] = h[n+1] = 0;	//处理边界
        q.push(0);
        for(int i = 1;i <= n;i++)	//单调栈模板
        {
            while(h[q.top()] >= h[i])
                q.pop();
            l[i] = q.top();
            q.push(i);
        }
        while(q.size())		//清空栈
            q.pop();
        q.push(n+1);
        for(int i = n;i >= 1;i--)
        {
            while(h[q.top()] >= h[i])
                q.pop();
            r[i] = q.top();
            q.push(i);
        }
        for(int i = 1;i <= n;i++)
            res = max(res,(LL)h[i]*(sum[r[i]-1]-sum[l[i]]));	//计算答案
        return res%1000000007;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值