题目链接: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;