zoukankan      html  css  js  c++  java
  • 【51nod】最大子段和

    题面

    以一个长为n的数列,求连续子段的最大值。

    思路1

    直接枚举O(n^3)TLE稳稳的

    #include<iostream>
    using namespace std;
    int n, a[50050], ans;
    int main(){
        cin>>n;
        for(int i = 1; i <= n; i++)cin>>a[i];
        for(int i = 1; i <= n; i++){//枚举起点
            for(int j = i; j <= n; j++){//枚举终点
                int t = 0;
                for(int k = i; k <= j; k++){//区间统计
                    t += a[k];
                }
                ans = max(ans, t);//更新最值
            }
        }
        cout<<ans<<"
    ";
        return 0;
    }

    前缀和优化的枚举法,O(N^2),还是TLE

    #include<iostream>
    using namespace std;
    int n, a[50050], ans;
    int main(){
        cin>>n;
        for(int i = 1; i <= n; i++){ cin>>a[i]; a[i]+=a[i-1];}
        for(int i = 1; i <= n; i++)//枚举起点
            for(int j = i; j <= n; j++)//枚举终点
                ans = max(ans, a[j]-a[i-1]);//更新最值
        cout<<ans<<"
    ";
        return 0;
    }

    思路2

    分治。以中间元素为基准,向左求出以中间元素为尾的最大子段和,向右求出以中间元素为首的最大子段和,两部分相加即横跨左右两部分的最大子段的和,三者最大即为答案。复杂度O(nlogn),可以水过,记得不开longlong会WA。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    int n, a[50050];
    LL dfs(int l, int r){
        if(l==r)return a[l]>0?a[l]:0;//所给整数均为负数时和为0。
        else{
            int m = l+r>>1;
            LL ls = dfs(l,m), rs = dfs(m+1,r);//左右两段单独
            //跨中间
            LL lsum = 0, lmax = 0;
            for(int i = m; i >= l; i--){
                lsum += a[i];
                lmax = max(lmax, lsum);
            }
            LL rsum = 0, rmax = 0;
            for(int i = m+1; i <= r; i++){
                rsum += a[i];
                rmax = max(rmax, rsum);
            }
            return max(lmax+rmax,max(ls,rs));
        }
    }
    int main(){
        cin>>n;
        for(int i = 1; i <= n; i++)cin>>a[i];
        cout<<dfs(1,n)<<"
    ";
        return 0;
    }

    思路3

    DP(覆盖了所有状态),如果当前记录的子段的和为负数时,就要以下一个点为起点重新找子段了。复杂度O(n),AC稳稳的。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    int n, a[50050];
    int main(){
        cin>>n;
        for(int i = 1; i <= n; i++)cin>>a[i];
        LL ans=0, t=0;
        for(int i = 1; i <= n; i++){
            if(t > 0)t += a[i];
            else t = a[i];
            ans = max(ans, t);
        }
        cout<<ans<<"
    ";
        return 0;
    }
  • 相关阅读:
    第二周学习小结
    第一周小结(^_^)
    VS2010和搜狗快捷键冲突
    解除SQL远程编辑表
    SQLServer2005mssqlserver服务与sqlexpress服务有什么区别
    OEA界面生成学习1 总体浏览
    WPF学习:绑定
    OutLook自动存档
    文件目录学习
    AQTime
  • 原文地址:https://www.cnblogs.com/gwj1314/p/9444876.html
Copyright © 2011-2022 走看看