https://codeforces.com/contest/1155/problem/D
题意
一个n个数的数组(a[i]),可以选择连续的一段乘x,求最大连续子序列的值
题解
- 错误思路:贪心,假如x<0,那么就选择最小的一段乘以x,再求最大连续子序列,因为这一段可能夹着一些很大的正数使得翻转一整段的代价很大,可能单独翻转前半段或者后半段更好
- 定义(f[i])为以i结尾的最大连续子序列,(g[i])为以i开头的最大连续子序列
- 假设选择翻转的区间是(l,r),则有(ans=max(f[l]+g[r+1]+sum[r]-sum[l]))
- 移项得:(sum[r]+g[r+1]+f[l]-sum[l]),可以枚举r,然后维护最大的(f[l]-sum[l])即可
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll x[300005],sum[300005],f[300005],g[300005],ans,mx;
int n,X;
int main(){
cin>>n>>X;
for(int i=1;i<=n;i++){
scanf("%lld",&x[i]);
sum[i]=sum[i-1]+x[i];
f[i]=max(x[i],f[i-1]+x[i]);
}
for(int i=n;i>=1;i--)
g[i]=max(g[i+1]+x[i],x[i]);
for(int r=0;r<=n;r++){
ans=max(ans,mx+max(0ll,g[r+1])+sum[r]*X);
mx=max(mx,max(0ll,f[r])-sum[r]*X);
}
cout<<ans;
}