http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1049
令 dp[i]表示为以a[i]结尾的最大子段和,则 dp[i]=max(dp[i-1]+a[i],a[i]);
包含a[i-1] : dp[i]=dp[i-1]+a[i];
不包含a[i-1] : dp[i]=a[i];
然后扫一遍dp[i]求出最大值。 时间复杂度O(n),空间复杂度 O(n);
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <string> 9 #include <set> 10 #include <functional> 11 #include <numeric> 12 #include <sstream> 13 #include <stack> 14 #include <map> 15 #include <queue> 16 #pragma comment(linker, "/STACK:102400000,102400000") 17 #define CL(arr, val) memset(arr, val, sizeof(arr)) 18 19 #define ll long long 20 #define inf 0x7f7f7f7f 21 #define lc l,m,rt<<1 22 #define rc m + 1,r,rt<<1|1 23 #define pi acos(-1.0) 24 25 #define L(x) (x) << 1 26 #define R(x) (x) << 1 | 1 27 #define MID(l, r) (l + r) >> 1 28 #define Min(x, y) (x) < (y) ? (x) : (y) 29 #define Max(x, y) (x) < (y) ? (y) : (x) 30 #define E(x) (1 << (x)) 31 #define iabs(x) (x) < 0 ? -(x) : (x) 32 #define OUT(x) printf("%I64d ", x) 33 #define lowbit(x) (x)&(-x) 34 #define Read() freopen("a.txt", "r", stdin) 35 #define Write() freopen("b.txt", "w", stdout); 36 #define maxn 1000000000 37 #define N 50010 38 #define mod 1000000000 39 using namespace std; 40 41 ll dp[N]; 42 ll f[N]; 43 44 int main() 45 { 46 int n; 47 scanf("%d",&n); 48 for(int i=0;i<n;i++) scanf("%lld",&f[i]); 49 dp[0]=f[0]; 50 for(int i=1;i<n;i++) 51 dp[i]=max(dp[i-1]+f[i],f[i]); 52 ll m=0; 53 for(int i=0;i<n;i++) 54 if(dp[i]>m) m=dp[i]; 55 printf("%lld ",m); 56 return 0; 57 }
可以发现其实 dp数组是不用保存的,我只要每次都更新一个最大值即可。空间复杂度可以优化成 O(1) .
#include<cstdio> #include<algorithm> using namespace std; int main() { int n; long long a,ans=0,m=0; scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%lld",&a); ans=max(ans+a,a); m=max(m,ans); } printf("%d ",m); return 0; }
更快速的方法是不断读取 数组元素 a,然后sum累加a,更新最大值,如果小于0,就置为0.这样省去调用库函数的时间。
1 #include<stdio.h> 2 int main() 3 { 4 __int64 sum,sum1,tem; 5 sum=sum1=0; 6 __int64 t,i; 7 scanf("%I64d",&t); 8 for(i=0;i<t;i++) 9 { 10 scanf("%I64d",&tem); 11 sum1=sum1+tem; 12 if(sum1<0) 13 sum1=0; 14 if(sum1>sum) 15 sum=sum1; 16 17 } 18 printf("%I64d ",sum); 19 }
保存最大字段和的起始和终止位置。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <string> 9 #include <set> 10 #include <functional> 11 #include <numeric> 12 #include <sstream> 13 #include <stack> 14 #include <map> 15 #include <queue> 16 #pragma comment(linker, "/STACK:102400000,102400000") 17 #define CL(arr, val) memset(arr, val, sizeof(arr)) 18 19 #define ll long long 20 #define inf 0x7f7f7f7f 21 #define lc l,m,rt<<1 22 #define rc m + 1,r,rt<<1|1 23 #define pi acos(-1.0) 24 25 #define L(x) (x) << 1 26 #define R(x) (x) << 1 | 1 27 #define MID(l, r) (l + r) >> 1 28 #define Min(x, y) (x) < (y) ? (x) : (y) 29 #define Max(x, y) (x) < (y) ? (y) : (x) 30 #define E(x) (1 << (x)) 31 #define iabs(x) (x) < 0 ? -(x) : (x) 32 #define OUT(x) printf("%I64d ", x) 33 #define lowbit(x) (x)&(-x) 34 #define Read() freopen("a.txt", "r", stdin) 35 #define Write() freopen("b.txt", "w", stdout); 36 #define maxn 1000000000 37 #define N 50010 38 #define mod 1000000000 39 using namespace std; 40 41 int main() 42 { 43 int n; 44 long long a,ans=0,m=0; 45 int begin,left,right; 46 scanf("%d",&n); 47 for(int i=0;i<n;i++) 48 { 49 scanf("%lld",&a); 50 if(ans>=0) 51 { 52 ans+=a; 53 } 54 else 55 { 56 ans=a; 57 begin=i; 58 } 59 if(ans>m) 60 { 61 left=begin; 62 right=i; 63 m=ans; 64 } 65 } 66 printf("%d %d %lld ",left,right,m); 67 return 0; 68 }