• 51nod最大字段和(1049 1254)


    1049是最大字段和的最朴素版本,1254加的地方是可以交换两个数一次。

    51nod 1049

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e5+1000;
    ll a[N];
    int n;
    ll solve()
    {
        ll sum=0;
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            if(sum>0)
                sum+=a[i];
            else sum=a[i];
            ans=max(ans,sum);
        }
        return ans;
    }
    int main()
    {
        //freopen("1.txt","r",stdin);
        cin>>n;
        ll sum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            sum+=a[i];
        }
        ll ans=solve();
        cout<<ans<<endl;
        return 0;
    }
    View Code

    51nod 1254

    交换两个数可以分为三类。

    1.交换的两个数都是最优解里面的。

    2.交换的两个数都不是最优解里面的。

    3.交换的两个数一个是最优解里面的,一个不是最优解里面的。

    只有第三种才可能会对答案有贡献。

    先考虑一边k<i,对于另一边分析类似。

    预处理求出每个i作为结束的最大字段为maxl[i],如果为负设为0;预处理求出每个i作为起点的最大字段和为maxr[i],如果为负设为0;

    对于每个i,求出左边的除最大字段和包含的点的最大值的点与i交换。贡献为maxl[i-1]+a[k]+maxr[i+1].

    代码实现用sum存储以i-1为结尾的字段和除左边处字段和包含的点的最大值的点的最大值。

    除左边字段和包含的所有点的最大值可以和左边字段和最大值之间可以隔负连通块,所以有sum=max(sum+a[i-1],maxx);

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=1e5+100;
    ll a[N],maxl[N],maxr[N];
    int main()
    {
        int n;
        //freopen("1.txt","r",stdin);
        cin>>n;
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            if(maxl[i-1]>0)
               maxl[i]=maxl[i-1]+a[i];
            else
               maxl[i]=a[i];
            if(maxr[n-i+2]>0)
               maxr[n-i+1]=maxr[n-i+2]+a[n-i+1];
            else
               maxr[n-i+1]=a[n-i+1];
            maxl[i]=max(maxl[i],0ll);
            maxr[n-i+1]=max(maxr[n-i+1],0ll);
            ans=max(ans,maxl[i]);
        }
        ll maxx=a[1],sum=0;
        for(int i=2;i<=n;i++)
        {
            sum=max(sum+a[i-1],maxx);
            ans=max(ans,sum+maxr[i+1]);
            maxx=max(maxx,a[i]);
        }
        maxx=a[n],sum=0;
        for(int i=n-1;i>=1;i--)
        {
            sum=max(sum+a[i+1],maxx);
            ans=max(ans,sum+maxl[i-1]);
            maxx=max(maxx,a[i]);
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    本学期的学习计划
    snmp 学习记录
    解锁树莓派root账号
    树莓派通过阿里云内网穿透,搭建下载机
    golang Ordered Map
    go 切片slice奇怪的地方
    学习scons总结
    go语言学习小结
    学习git版本管理工具
    轻松记账工程冲刺第二阶段10
  • 原文地址:https://www.cnblogs.com/flyljz/p/14076303.html
Copyright © 2020-2023  润新知