• 【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;
    }
  • 相关阅读:
    一种基于HBase韵海量图片存储技术
    八种常用的排序算法
    hibernate session的常用方法解析
    EJB到底是什么,真的那么神秘吗??<转>
    一名实习生在腾讯的感受<很值得一看>
    Jenkins持续集成报告列表显示不正确的问题解决
    Jenkins配置,tomacat版本输出乱码和页面打开报404的问题
    Jenkins部署持续集成远程机节点的问题
    浅析软件测试人员如何对JVM进行内存溢出检测
    python自动化测试,读取excal数据报"'str' object has no attribute 'items'"问题解决
  • 原文地址:https://www.cnblogs.com/gwj1314/p/9444876.html
Copyright © 2020-2023  润新知