最大子段和,但是两段# Kadane

思路: 

  1. 左侧最大子数组和计算(l数组)

    • 使用 Kadane 算法计算以每个位置i结尾的最大子数组和
    • l[i]表示从数组开始到位置i的最大子数组和
  2. 右侧最大子数组和计算(r数组)

    • 反向使用 Kadane 算法计算以每个位置i开头的最大子数组和
    • r[i]表示从位置i到数组末尾的最大子数组和
  3. 组合结果

    • 枚举所有可能的分割点i(0 ≤ i ≤ n-2)
    • 对于每个分割点,计算l[i] + r[i+1],找到最大值

 

#include <iostream>
#include <vector>
#include <climits>
#include <algorithm>
using namespace std;

int main() {
    // 优化输入输出性能(关闭同步和解除绑定)
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t; 
    cin >> t; // 读取测试用例数量
    
    while (t--) { // 处理每个测试用例
        int n; 
        cin >> n; // 读取数组长度
        
        vector<int> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i]; // 读取数组元素
        }
        
        // 计算左侧最大子数组和(以每个位置结尾的最大子数组和)
        vector<long long> l(n); // l[i] 表示从索引0到i的最大子数组和
        long long s = 0, m = LLONG_MIN; // s维护当前子数组和,m维护历史最大子数组和
        for (int i = 0; i < n; i++) {
            // 状态转移:要么加入当前元素到之前的子数组,要么从当前元素重新开始
            s = max(s + a[i], (long long)a[i]);
            m = max(m, s); // 更新历史最大值
            l[i] = m; // 记录到当前位置i的最大子数组和
        }
        
        // 计算右侧最大子数组和(以每个位置开头的最大子数组和)
        vector<long long> r(n); // r[i] 表示从索引i到n-1的最大子数组和
        s = 0, m = LLONG_MIN; // 重置变量用于反向计算
        for (int i = n - 1; i >= 0; i--) {
            // 同理,反向计算最大子数组和
            s = max(s + a[i], (long long)a[i]);
            m = max(m, s);
            r[i] = m; // 记录从当前位置i开始到末尾的最大子数组和
        }
        
        // 计算最大和(通过枚举所有可能的分割点)
        long long res = LLONG_MIN; // 初始化结果为最小值
        for (int i = 0; i < n - 1; i++) {
            // 对于每个分割点i,左侧最大子数组和为l[i],右侧最大子数组和为r[i+1]
            res = max(res, l[i] + r[i + 1]);
        }
        
        cout << res << '\n'; // 输出结果
    }
    
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值