CSU

来源:互联网 发布:游族网络股票千股千评 编辑:程序博客网 时间:2024/05/18 01:39

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1529


题解:

一个加强版的最大连续和子序列,序列可以从末尾元素转到首元素。

分两种情况:

1.最大连续和不需要尾接首,直接dp出以a[i]为结尾的最大连续和ma[i]。

2.最大连续和需要尾接首,先dp出以a[i]为结尾的最小连续和mi[i],然后再用总和sum减去mi[i],得到的即为减去中间部分的尾接首序列和(逆向思维)。最后再用max()取最大值。



代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <string>#include <vector>#include <map>#include <set>#include <queue>#include <sstream>#include <algorithm>using namespace std;#define pb push_back#define mp make_pair#define ms(a, b)  memset((a), (b), sizeof(a))//#define LOCAL#define eps 0.0000001#define LNF (1<<60)typedef long long LL;const int inf = 0x3f3f3f3f;const int maxn = 2000000+10;const int mod = 1e9+7;LL a[maxn];LL ma[maxn], mi[maxn];void solve(){    int n;    scanf("%d",&n);    LL sum = 0;    for(int i = 1; i<=n; i++)        scanf("%lld",&a[i]), sum += a[i];    LL now = 0;    for(int i = 1; i<=n; i++)//最大连续和    {        if(now>=0)            ma[i] = a[i]+now, now += a[i];        else            ma[i] = a[i], now = a[i];    }    now = 0;    for(int i = 1; i<=n; i++)//最小连续和    {        if(now<= 0)            mi[i] = a[i] + now, now += a[i];        else            mi[i] = a[i], now = a[i];    }    LL ans = ma[1];    for(int i = 1; i<=n; i++)//寻找最大值    {        ans = max(ans, ma[i]);        ans = max(ans, sum-mi[i]);    }    printf("%lld\n",ans);}int main(){#ifdef LOCAL    freopen("input.txt", "r", stdin);//      freopen("output.txt", "w", stdout);#endif // LOCAL    int t;    scanf("%d", &t);    while(t--){        solve();    }    return 0;}


0 0
原创粉丝点击