翻转 题解

翻转

https://ac.nowcoder.com/acm/contest/7738/B

仔细观察一下,发现要求的就是环上两段最大子段和,因为你总是可以通过翻转把这两段拼在一起。

这是一个经典问题(Luogu),直接正反贪心一遍拼在一起,取相反数后再做一次即可。

需要注意的是可能要特判全是负数的情况。

// ====================================
//   author: M_sea
//   website: https://m-sea-blog.com/
// ====================================
#include <bits/stdc++.h>
#define file(x) freopen(#x".in","r",stdin); freopen(#x".out","w",stdout)
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;

int read() {
    int X=0,w=1; char c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
    return X*w;
}

const int N=200000+10;

int n,a[N],cnt=0; ll sum=0;

ll f[N],g[N];
ll calc() {
    for (int i=1;i<=n;++i) f[i]=max(f[i-1],0ll)+a[i];
    for (int i=n;i>=1;--i) g[i]=max(g[i+1],0ll)+a[i];
    for (int i=1;i<=n;++i) f[i]=max(f[i-1],f[i]);
    for (int i=n;i>=1;--i) g[i]=max(g[i+1],g[i]);
    ll res=-1e18;
    for (int i=1;i<n;++i) res=max(res,f[i]+g[i+1]);
    return res;
}

int main() {
    n=read();
    for (int i=1;i<=n;++i) a[i]=read(),sum+=a[i],cnt+=(a[i]>0);
    if (!cnt) {
        int ans=-1e18;
        for (int i=1;i<=n;++i) ans=max(ans,a[i]);
        printf("%d\n",ans);
        return 0;
    }
    ll ans1=calc();
    for (int i=1;i<=n;++i) a[i]=-a[i];
    ll ans2=calc(); if (!ans2) ans2=-1e18;
    printf("%lld\n",max(ans1,sum+ans2));
    return 0;
}
全部评论
代码过不了
点赞 回复 分享
发布于 2022-06-10 17:21
Orz M_sea
点赞 回复 分享
发布于 2020-10-14 18:55
Orz M_sea
点赞 回复 分享
发布于 2020-10-02 21:35

相关推荐

不愿透露姓名的神秘牛友
昨天 20:15
点赞 评论 收藏
分享
野猪不是猪🐗:我assume that你must技术aspect是solid的,temperament也挺good的,however面试不太serious,generally会feel style上不够sharp
点赞 评论 收藏
分享
刘湘_passion:太强了牛肉哥有被激励到
点赞 评论 收藏
分享
评论
6
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务