P1115 最大子段和

博客介绍了最大子序列问题的算法。提到可用贪心递推\(O(n)\)解决,也因线段树和平衡树需求,介绍了\(O(nlogn)\)的分治法。分治法将区间分开,最大子序列可能在左、右或横跨左右区间,对不同情况分别处理。

没错,我变菜了。。。

这道题可以用贪心的递推\(O(n)\)地搞过去。

但是因为线段树和平衡树也要支持最大子序列,所以回来了解一波\(O(nlogn)\)的算法。

算法思想也非常常见:分治法。

对于一个区间\([l,r]\),我们从中间给他分开,变成\([l,mid]\)\([mid+1,r]\)这两个区间。

而最大子序列可能出现的地方就有三个。一个在左区间,一个横跨左右区间,一个在右区间。

对于全部在一个区间的,我们递归搞一搞。

对于横跨左右区间的,我们可以暴力\(O(n)\)地枚举左区间内以\(mid\)结束的最大子序列右区间内以\(mid+1\)开始的最大子序列,两个相加就完事了。

代码:

int solve(int l, int r)
{
    if(l == r) return a[l];
    int mid = (l + r) >> 1;
    int rec1 = -INF, rec2 = -INF;
    int sum = 0;
    for(int i = mid; i >= l; i--)
    {
        sum += a[i];
        rec1 = std::max(rec1, sum);
    }
    sum = 0;
    for(int i = mid + 1; i <= r; i++)
    {
        sum += a[i];
        rec2 = std::max(rec2, sum);
    }
    return std::max(rec1 + rec2, std::max(solve(l, mid), solve(mid + 1, r)));
}

转载于:https://www.cnblogs.com/Garen-Wang/p/9564813.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值