B

地址: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;
}
原文地址:https://www.cnblogs.com/liyexin/p/12716621.html