P4095. 乘积最大子数组

题目内容
给你一个整数数组nums,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个32-位整数。

输入描述
一个整数数组nums

输出描述
一个整数表示最大乘积

样例1
输入
2 3 -2 4
输出
6
说明
子数组[2,3]有最大乘积6。

样例2
输入
-2 0 -1
输出
0

说明
结果不能为 2, 因为[-2,-1]不是子数组。

提示:
\(1 <= nums.length <= 2 * 10^4\)
\(-10 <= nums[i] <= 10\)
nums 的任何子数组的乘积都保证是一个 32-位 整数

由于数组中既可能有正数也可能有负数,负数相乘会使得结果变正,同时遇到 0 时会将乘积清零,因此我们需要同时记录当前子数组的最大值和最小值。具体思路如下:

定义 dp_{max}[i]表示以下标 i 结尾的子数组所能获得的最大乘积;
定义 dp_{min}[i]表示以下标 i 结尾的子数组所能获得的最小乘积;

当遇到负数时,由于负负得正,当前最大值可能由之前的最小值乘以当前值得到;
状态转移公式为

\(dp_{max}[i] = max(nums[i], dp_{max}[i-1] * nums[i], dp_{min}[i-1] * nums[i])\)
\(dp_{min}[i] = min(nums[i], dp_{min}[i-1] * nums[i], dp_{min}[i-1] * nums[i])\)

同时维护全局最大值即可。

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+100;
int a[maxn];
int n=0,x;
int maxval[maxn];
int minval[maxn];
int ans=0;
int main(){
	maxval[0]=1;
	minval[0]=1;
	while(cin>>x){
		a[++n]=x;
	}
	for(int i=1;i<=n;i++){
		maxval[i]=max(a[i],max(maxval[i-1]*a[i],minval[i-1]*a[i]));
		minval[i]=min(a[i],min(minval[i-1]*a[i],maxval[i-1]*a[i]));
		ans=max(ans,max(maxval[i],a[i]));
	}
	cout<<ans<<endl;
}
posted @ 2025-08-05 11:22  lipu123  阅读(9)  评论(0)    收藏  举报