您的位置:首页 > 其它

CSU - 1529 Equator —— DP 最大连续和子序列

2017-04-25 10:15 381 查看
题目链接: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: