地址:https://www.luogu.com.cn/problem/CF33C
题意:
给你一个序列,你可以选择它的前缀和后缀中的每个数字都乘以-1。前缀和后缀可以交叉也可以为空。
问能得到的最大序列和是多少。
解析:假设这个序列分成了三部分:A(前缀)+B(重合)+C(后缀) S=A+B+C。重合部分,*-1两次,值不变,就相当于没有操作。
-(A+C)+B是更改后的序列和,而之前A+B+C=S,那么可以变成:-(S-B)+B=2*B-S。求这个最大值,S固定,那么只要保证B最大就好了。B怎么保证最大?它就是最大子序列的和。关于它的DP求法,我的这个博客里有写:https://www.cnblogs.com/liyexin/p/11693281.html。结果输出2*maxx-sum即可
#include<iostream> using namespace std; typedef long long ll; const int maxn=1e5+10; ll a[maxn]; ll dp[maxn]; int qk(ll a, ll b,ll c) { ll ans=1; a=a%c; while(b) { if(b%2==1) ans=(ans*a)%c; b=b/2; a=(a*a)%c; } return ans; } int main() { int n; cin>>n; ll sum=0; for(int i=1;i<=n;i++) { cin>>dp[i]; sum+=dp[i]; } ll maxx=dp[1]; int k; for(int i=2;i<=n;i++) { if(dp[i-1]>=0) { dp[i]+=dp[i-1]; } if(dp[i]>maxx) { maxx=dp[i]; } } if(maxx<0) maxx=0; cout<<maxx*2-sum<<endl; }