P1121 环状最大两段子段和

非环状最大两子段和

fr[i]1iba[i]nimax(fr[i]+ba[i+1])i[1,n)

int Solve(){
int ans=-0x3f3f3f3f;
for(int i=1;i<=n;i++) fr[i]=max(fr[i-1],0ll)+a[i];
for(int i=1;i<=n;i++) fr[i]=max(fr[i],fr[i-1]);
for(int i=n;i>=1;i--) ba[i]=max(ba[i+1],0ll)+a[i];
for(int i=n;i>=1;i--) ba[i]=max(ba[i],ba[i+1]);
for(int i=1;i<n;i++)
ans=max(ans,fr[i]+ba[i+1]);
return ans;
}

环状最大两子段和

  • 求非环状最大两子段和 ans1,再求非环状最小两子段和 ans2,这样两个最小子段和能把环分成两部分,就是环状最大两子段和sum+ans2(),与非环状最大两子段和取最大值即可

  • 求非环状最小两子段和,其实就是求原序列的相反数的非环状最大两子段和,但是如果序列中只有一个正数会导致所求的非环状最大两子段相连,只将序列分为一部分,所以如果序列中只有一个正数,那么答案就是非环状最大两子段和‘

  • 如果序列中全为负数,那么原序列的相反数的非环状最大两子段和会等于原序列和的相反数,导致sum+ans2=0,无效,所以答案就是ans1

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int n;
int a[N],fr[N],ba[N];
int sum,cnt,ans1,ans2;
int Solve(){
int ans=-0x3f3f3f3f;
for(int i=1;i<=n;i++) fr[i]=max(fr[i-1],0ll)+a[i];
for(int i=1;i<=n;i++) fr[i]=max(fr[i],fr[i-1]);
for(int i=n;i>=1;i--) ba[i]=max(ba[i+1],0ll)+a[i];
for(int i=n;i>=1;i--) ba[i]=max(ba[i],ba[i+1]);
for(int i=1;i<n;i++)
ans=max(ans,fr[i]+ba[i+1]);
return ans;
}
signed main(){
freopen("1.in","r",stdin);
memset(fr,-0x3f3f3f3f,sizeof(fr));
memset(ba,-0x3f3f3f3f,sizeof(ba));
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
if(a[i]>0) cnt++;
}
ans1=Solve();
if(cnt==1){
cout<<ans1<<"\n";
}else{
memset(fr,-0x3f3f3f3f,sizeof(fr));
memset(ba,-0x3f3f3f3f,sizeof(ba));
for(int i=1;i<=n;i++)
a[i]=-a[i];
ans2=sum+Solve();
if(!ans2) ans2=-0x3f3f3f3f;
cout<<max(ans1,ans2)<<"\n";
}
}
posted on   Bubble_e  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】



点击右上角即可分享
微信分享提示