zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    权限管理
    用户和用户管理
    文本编辑器vim
    对于我的linux常用命令的说明
    linux常用命令6:关机重启命令
    linux常用命令:5网络命令
    linux常用命令:4文件压缩和解压命令
    linux常用命令:3文件搜索命令
    linux常用命令:2权限管理命令
    通过原型继承创建一个新对象
  • 原文地址:https://www.cnblogs.com/flyljz/p/14076303.html
Copyright © 2011-2022 走看看