最大子序列和

##子序列:
可以不连续,但是要保证出现的顺序与原字符串相同

给定一个整数序列A1,A2…An。求最大的连续的子序列的和。
比如{1,-2,3,1,-1,2}的最大连续子序列的和为5(3+1-1+2)

1.定义状态:
dp[i]表示以a[i]为结尾的连续子序列的最大和
2.状态转移:
if(dp[i-1]>0) dp[i]=dp[i-1]+a[i];
else dp[i]=a[i];

int sum=ans=0;
for(int i=1; i<=n; i++)
{
   sum=max(sum,0)+a[i];
   ans=max(ans,sum);
}

###例题
最大子段和

N个整数组成的序列a1,a2,a3,…,an, 求该序列如ai+ai+1+…+aj的连续子段和的最大值。当所给的整数均为负数时和为0。
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
Input
第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N + 1行:N个整数(-10^9 <= Aii <= 10^9)
Output
输出最大子段和。
Sample Input
6
-2
11
-4
13
-5
-2
Sample Output
20

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
    int n;
    long long a[50000];
    cin>>n;
    for(int i=0; i<n; i++)
        cin>>a[i];

    long long sum=0,ans=0;
    for(int i=0; i<n; i++)
    {
        sum=sum>0 ? sum+a[i] : a[i];
        ans=ans>sum ? ans : sum;
    }
    cout<<ans<<endl;

}

循环数组最大子段和
N个整数组成的循环序列a1,a2,a3,…,an,求该序列如ai+ai+1+…+aj的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑an−1,an,a1,a2这样的序列)。当所给的整数均为负数时和为0。
例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
Input
第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N+1行:N个整数 (-10^9 <= Si<= 10^9)
Output
输出循环数组的最大子段和。
Sample Input
6
-2
11
-4
13
-5
-2
Sample Output
20

题解分析:
这与上面的例题不同,最大值有可能存在于起始与末尾相连的地方。
首先求出不是首尾相连时的最大子序列的值,然后,将所有的数求反,再求一次最大子序列(此时就相当于求原序列的中间的最小值),再与原始所有数的和相加(原序列的总和减去中间的最小和得到两头的最大值和),得到的便是首尾相连时的首与尾的最大子序列和,然后再与中间的最大值相比较,取最大值。

#include<iostream>
using namespace std;
typedef long long ll;
ll t=0; 
ll a[50001];
int main()
{
 int n;
 cin>>n;
 ll sum=0,sum1=0,ans=0,ans1=0;
 for(int i=0; i<n; i++)
    cin>>a[i];

 for(int i=0; i<n; i++)
    {
      sum1=max(sum1,t)+a[i];
      ans1=max(sum1,ans1);
    }
 for(int i=0; i<n; i++)
 {
    sum+=a[i];
    a[i]=-1*a[i];
 }
 sum1=0;
 for(int i=0; i<n; i++)
 {
   sum1=max(sum1,t)+a[i];
   ans=max(ans,sum1);
 }
 ans=ans+sum;
 ans=max(ans,ans1);
 cout<<ans<<endl;
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值