LA 3839 动态最大连续和(线段树)(训练指南)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4146

要求给定区间的最大连续和,主要维护相关信息,prefix最大前缀和,suffix最大后缀和,sum-Max区间最大连续和。

区间的最大连续和=max( max(sum-Max(rt<<1),sum-Max(rt<<1|1)),suffix(rt<<1)+prefix(rt<<1|1)).

参考了这个人的解题报告,详细代码就不贴了

http://blog.csdn.net/c3568/article/details/8573811

主要是利用子结点更新父亲结点。

主要注释:

struct SegmentTree
{
    LL sum,sum_max,prefix,suffix;
    int l,r,p,s;///l代表区间最大和的起点,r代表区间最大和的终点,p代表前缀和的终点,s代表后缀和的起点
} f[maxn<<2];

最大前缀和更新:

f[rt].prefix=f[lc].prefix,f[rt].p=f[lc].p;
if(f[rt].prefix<f[lc].sum+f[rc].prefix)
       f[rt].prefix=f[lc].sum+f[rc].prefix,f[rt].p=f[rc].p;

最大后缀和更新:

f[rt].suffix=f[rc].suffix,f[rt].s=f[rc].s;
if(f[rt].suffix<=f[lc].suffix+f[rc].sum)///要x,y都尽可能的小,所以加等号
        f[rt].suffix=f[lc].suffix+f[rc].sum,f[rt].s=f[lc].s;

最大连续和更新:

if(f[lc].sum_max>=f[rc].sum_max) f[rt].sum_max=f[lc].sum_max,f[rt].l=f[lc].l,f[rt].r=f[lc].r;
else f[rt].sum_max=f[rc].sum_max,f[rt].l=f[rc].l,f[rt].r=f[rc].r;
LL a=f[rt].sum_max,b=f[lc].suffix+f[rc].prefix;
if(b>a||(a==b&&f[rt].l>f[lc].s)||(a==b&&f[rt].l==f[lc].s&&f[rt].r>f[rc].p))
     f[rt].sum_max=b,f[rt].l=f[lc].s,f[rt].r=f[rc].p;

区间查询返回信息(参看上面链接,写的很详细)

你可能感兴趣的:(LA 3839 动态最大连续和(线段树)(训练指南))