P2642 双子序列最大和-前缀最大子段和与后缀最大字段和

题目链接双子序列最大和 - 洛谷

直接找肯定麻烦,不如枚举分界点

dpright[i]代表以i为结尾的最大子段和

 for(int i=1;i<=n;i++)
     {
         dpright[i]=max(dpright[i-1]+a[i],a[i]);

     }

我们进行一下下面操作,dpright[i]就变成了可能包括i在内 的i之前的最大子段和

 for(int i=1;i<=n;i++)
     {
         dpright[i]=max(dpright[i-1],dpright[i]);

     }

同理,设置dpleft[i]为i开头的,向后扩展的最大子段和,需要从后往前推,从后往前转移

 for(int i=n;i>=1;i--)
     {
         dpleft[i]=max(dpleft[i+1]+a[i],a[i]);

     }

然后枚举断点i,由于距离至少隔一个数所以dpright[i-1]+dpleft[i+1]就是以i为分界点,距离至少隔1的双序列最大子段和

#include<iostream>
#include<set>
# include<algorithm>
# include<cstring>

using namespace std;
typedef long long int ll;

int a[1000000+10];
int dpright[1000000+10];
int dpleft[1000000+10];

int main()
{

     fill(dpright,dpright+1000000+10,-9999999);
     fill(dpleft,dpleft+1000000+10,-9999999);

     int n;
     cin>>n;

     for(int i=1;i<=n;i++)
     {
         scanf("%d",&a[i]);

     }


     for(int i=1;i<=n;i++)
     {
         dpright[i]=max(dpright[i-1]+a[i],a[i]);

     }

     for(int i=n;i>=1;i--)
     {
         dpleft[i]=max(dpleft[i+1]+a[i],a[i]);

     }


     for(int i=1;i<=n;i++)
     {
         dpright[i]=max(dpright[i-1],dpright[i]);

         dpleft[n-i+1]=max(dpleft[n-i+2],dpleft[n-i+1]);

     }
     int ans=-99999999;


     for(int i=2;i<=n;i++)
     {
         ans=max(ans,dpright[i-1]+dpleft[i+1]);

     }

     cout<<ans;


    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值