P1121 环状最大两段子段和
非环状最大两子段和
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; }
环状最大两子段和
-
求非环状最大两子段和
,再求非环状最小两子段和 ,这样两个最小子段和能把环分成两部分,就是环状最大两子段和 ,与非环状最大两子段和取最大值即可 -
求非环状最小两子段和,其实就是求原序列的相反数的非环状最大两子段和,但是如果序列中只有一个正数会导致所求的非环状最大两子段相连,只将序列分为一部分,所以如果序列中只有一个正数,那么答案就是非环状最大两子段和‘
-
如果序列中全为负数,那么原序列的相反数的非环状最大两子段和会等于原序列和的相反数,导致
,无效,所以答案就是
代码
#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"; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】