Educational Codeforces Round 63 (Rated for Div. 2) D dp(最大連續子序列)
阿新 • • 發佈:2019-05-05
pre Education -- tps ont fine ble ted ()
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]\)
代碼
#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; }
Educational Codeforces Round 63 (Rated for Div. 2) D dp(最大連續子序列)