题目链接:http://codeforces.com/contest/1155/problem/D
题意:给一个数组a,一个整数x,可以挑选数组a的任意一个连续区间(可以为空)将区间内的值都乘以x,求操作之后得到的最大连续子区间和值
思路:dp[i][0]存0~i位中都没乘过x的以第i位结尾的子区间的最大和,dp[i][1]存0~i位中以i位结尾的子区间且该子区间结尾部分是乘以x的,dp[i][2]存0~i位中以i位结尾的子区间且该子区间中有一个连续子区间乘以x且第i位没有乘以x
得到状态转移方程:
dp[i][2] = max(dp[i-1][2] + a[i], dp[i-1][1] + a[i])
dp[i][1] = max(dp[i-1][1] + a[i] * x, dp[i-1][0] + a[i] * x)
dp[i][0] = max(0,max(a[i], dp[i-1][0] + a[i]))
代码:
#include<iostream>
#include <cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<functional>
#include <unordered_map>
#include<queue>
#include<cmath>
#include<unordered_map>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 50;
ll a[maxn];
ll dp[5], la[5];
int main()
{
int n, x;
scanf("%d%d", &n, &x);
for (int i = 0; i < n; i++)
{
scanf("%lld", &a[i]);
}
dp[0] = max((ll)0, a[0]);
dp[1] = max((ll)0, a[0] * x);
dp[2] = max((ll)0, a[0] * x);
ll ans = max(dp[0], max(dp[1], dp[2]));
for (int i = 1; i < n; i++)
{
dp[2] = max(dp[2] + a[i], dp[1] + a[i]);
ans = max(ans, dp[2]);
dp[1] = max(dp[1] + a[i] * x, dp[0] + a[i] * x);
ans = max(ans, dp[1]);
dp[0] = max((ll)0,max(a[i], dp[0] + a[i]));
ans = max(ans, dp[0]);
}
printf("%lld\n", ans);
}