首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

最大連續子序列和 (HDU 1003) 五種解法總結

     編輯:關於C++

問題

給定序列 a[1..n] (n≤100000),求最大子段和及其起始、結束位置 (多解取起點最小、再取終點最小)。T≤20 組測試。

方法對比

方法時間複雜度備註
三重循環枚舉O(n³)超時
前綴和雙循環O(n²)超時
分治法O(n log n)可 AC
線段樹O(n log n)可 AC,代碼長
掃描法 (Kadane)O(n)最優,代碼最短

掃描法核心邏輯

int maxSum = -INF, curSum = 0;
int start = 1, end = 1, tempStart = 1;
for (int i = 1; i <= n; ++i) {
    curSum += a[i];
    if (curSum > maxSum) {
        maxSum = curSum;
        start = tempStart;
        end = i;
    }
    if (curSum < 0) {
        curSum = 0;
        tempStart = i + 1;
    }
}

完整代碼 (C++)

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
int a[100010];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T; cin >> T;
    for (int cs = 1; cs <= T; ++cs) {
        int n; cin >> n;
        for (int i = 1; i <= n; ++i) cin >> a[i];
        int maxSum = -INF, curSum = 0;
        int L = 1, R = 1, tmpL = 1;
        for (int i = 1; i <= n; ++i) {
            curSum += a[i];
            if (curSum > maxSum) {
                maxSum = curSum; L = tmpL; R = i;
            }
            if (curSum < 0) { curSum = 0; tmpL = i + 1; }
        }
        cout << "Case " << cs << ":\n" << maxSum << ' ' << L << ' ' << R << "\n";
        if (cs != T) cout << "\n";
    }
    return 0;
}

分治法思想 (補充)

遞歸求左半、右半、跨中間最大子段和。跨中間從中點向左右擴展維護最大前綴/後綴和。結構體保存 {值, 左, 右} 便於合併。

線段樹節點信息

每節點維護:區間和、最大前綴和/位置、最大後綴和/位置、最大子段和/位置。合併操作利用結合律,查詢整個區間即得答案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved