• 【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;
    }
  • 相关阅读:
    java与C#、.NET AES加密、解密 解决方案
    java 类名.class、object.getClass()和Class.forName()的区别 精析
    java instanceof和isInstance的关系 精析
    java 反汇编class文件
    织梦默认分页样式改动 解决分页列表显示,去掉li
    The method Inflate() in android
    leetcode第一刷_Edit Distance
    codeforces round #264(div2)
    android开发游记:SpringView 下拉刷新的高效解决方式,定制你自己风格的拖拽页面
    《linux 内核全然剖析》 chapter 4 80x86 保护模式极其编程
  • 原文地址:https://www.cnblogs.com/gwj1314/p/9444876.html
Copyright © 2020-2023  润新知