题目大意:
给你一个序列。你可以选择一段子序列让里面每个数 ∗ x *x ∗x.问你最大字段和 。
题目思路:
答案要么是:原序列最大子段和。要么:
暴力 n 2 n^2 n2枚举这个子序列的位置.计算结果。再拼接上左右两端的最大字段和.即为结果。
现在考虑优化:
我们发现最终答案区间一定分三段,第一段是以 L − 1 L-1 L−1为结尾的最大字段和,第二段 [ L , R ] [L,R] [L,R]是每个数相加*x,第三段也是以 R + 1 R+1 R+1开头的最大字段和。所以用状态机模型,分三个阶段进行.
d p ( i , 1 / 2 / 3 ) dp(i,1/2/3) dp(i,1/2/3)代表第 i i i个位置且当前为答案区间的第j段时的最大区间和。转移即可。
但是说实话,真的这题挺难想的.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<ll,ll>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
ll a[maxn] , dp[maxn][3];
int main()
{
ios::sync_with_stdio(false);
int n , x; cin >> n >> x;
for (int i = 1 ; i <= n ; i++)
cin >> a[i];
ll ans = 0;
for (int i = 1 ; i <= n ; i++){
dp[i][0] = max(dp[i - 1][0] , 0ll) + a[i];
dp[i][1] = max(max(dp[i - 1][0],dp[i - 1][1]) , 0ll) + x * a[i];
dp[i][2] = max(max(dp[i - 1][0],max(dp[i - 1][1] , dp[i - 1][2])) , 0ll) + a[i];
ans = max(ans , max(dp[i][0] , max(dp[i][1] , dp[i][2])));
}
cout << ans << endl;
return 0;
}