娜娜梦游仙境系列——吃不完的糖果
娜娜好不容易才在你的帮助下"跳"过了这个湖,果然车到山前必有路,大战之后必有回复,大难不死,必有后福!现在在娜娜面前的就是好多好多的糖果还有一些黑不溜秋的东西!不过娜娜眼中只有吃不完的糖果!娜娜高兴地快要蹦起来了!
这时有一位挥着翅膀的女孩(天使?鸟人?)飞过来,跟娜娜说,这些糖果是给你的~(娜娜已经两眼放光)~你可以带走~(娜娜已经流下了口水)~但是~(神马?还有但是?)~这位神仙姐姐挥一挥翅膀~飘过了一片云彩,糖果和那些黑不溜秋的东西顿时飞了起来,落到地上成了摆成一个奇怪的图形。
神仙姐姐很满意,转过来对娜娜说:“这些糖果和黑洞(神马?黑洞?)分成n堆,每堆要么都是糖果,要么是黑洞,围成一个圈(即第1堆的旁边是第n堆和第2堆),你可以选择连续若干堆,然后带走,不过这些黑洞嘛,会馋嘴的小孩吸进去,你必须拿糖果去中和掉。”
娜娜喜欢糖果,但不喜欢动脑子~于是就把这个问题交给你,怎样才能让娜娜带走最多的糖果呢?
多组数据,首先是一个正整数t(t<=20)表示数据组数
对于每组数据,包括两行,第一行是一个正整数n(3<=n<=100000)表示堆数
第二行是n个整数x[i](1<=|x[i]|<=1000),如果是个正整数,则说明这是一堆数量为x[i]的糖果,如果是个负整数,则说明这是一个需要用abs(x[i])颗糖果去中和的黑洞。
对于每组数据,输出一个整数,表示娜娜最多能带走的糖果数。
3 5 1 2 3 4 5 5 1 -2 3 -4 5 5 -1 -2 -3 -4 -5
15 7 0提示: 对于样例1,娜娜可以把所有的糖果都拿走,所以输出15(=1+2+3+4+5) 对于样例2,娜娜可以拿走第1,2,3,5堆的糖果,别忘了这是摆成一个圈,所以输出7(=1+(-2)+3+5) 对于样例3,等待娜娜的是5个黑洞,可怜的娜娜,一个糖果都拿不掉,所以输出0 由于输入数据较多,请谨慎使用cin/cout
题意:n个数构成一个环,问最大子串和是多少。
解法:首先你要学会不是环的最大子串和的O(n)DP算法。 普通的最大子串和的具体实现如下 用dp[i]来表示以该数a[i]结尾的最大子串和,转移为dp[i]=max(dp[i-1]+a[i],a[i]),这句表达式用自然语言说就是,考虑自己是跟着前一项还是新开一个子串,如果中断与前一项的联系会更优(即和更大),那么就让自己作为新的子串,否则就跟着前一项。 那么如果是环怎么办呢?我们可以发现其实答案只有两种,要么是不需要经过1,n的交界,这样只需当成普通的子串和就行了,如果经过1,n的交界呢?我们会发现等价于整个数列去掉中间的一块连续子串,要使剩下的最大,那么肯定要让去掉的子串和最小,怎么求最小子串和?把所有数取相反数再跑一次最大子串和即可。比较两个方案,输出最大的就是答案。
//china no.1
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1e4+10;
const int maxx=1e5+100;
const double EPS=1e-7;
const int MOD=10000007;
#define mod(x) ((x)%MOD);
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
inline LL Scan()
{
LL Res=0,ch,Flag=0;
if((ch=getchar())=='-')Flag=1;
else if(ch>='0' && ch<='9')Res=ch-'0';
while((ch=getchar())>='0'&&ch<='9')Res=Res*10+ch-'0';
return Flag ? -Res : Res;
}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.out" , "w" , stdout );
//cerr << "run time is " << clock() << endl;
int n,sum,a[maxx],dp[maxx];
int solve()
{
me(dp,0);
dp[1]=max(0,a[1]);
int ma=dp[1];
FOR(2,n,i)
{
dp[i]=max(dp[i-1]+a[i],a[i]);
if(ma<dp[i])
ma=dp[i];
}
return ma;
}
int main()
{
int t;
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
cin>>n;sum=0;
FOR(1,n,i)
{
cin>>a[i];
sum+=a[i];
}
int maxc=solve();
FOR(1,n,i)
a[i]=-a[i];
int maxz=solve()+sum;
printf("%d\n",max(maxz,maxc));
}
}
}