【51nod】最大子段和

小哈里發表於2018-04-17

題面

以一個長為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<<"\n";
    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<<"\n";
    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)<<"\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<<"\n";
    return 0;
}

相關文章