地址: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求法,结果输出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;
}