区间最大连续字段
线段树多维护三个值:当前区间从左端开始最大连续和cl,从右端开始最大连续和cr,区间内最大连续和m
cl等于max(左子区间和s+右子区间cl,左子区间cl)
cr等于max(右子区间和s+左子区间cr,右子区间cr)
m等于max(左子区间m,右子区间m,左子区间cr+右子区间cl)
查询时返回区间段并不断合并。
struct node
{
int s,cl,cr,m;
}tree[4*500000];
void pushup(int now,int ls,int rs,int l,int r,int mid)
{
tree[now].s=tree[ls].s+tree[rs].s;
tree[now].m=max(tree[ls].m,max(tree[rs].m,tree[ls].cr+tree[rs].cl));
tree[now].cl=max(tree[ls].cl,tree[ls].s+tree[rs].cl);
tree[now].cr=max(tree[rs].cr,tree[rs].s+tree[ls].cr);
}
void build(int l,int r,int now)
{
if(l==r)
{
scanf("%d",&tree[now].s);
tree[now].m=tree[now].cl=tree[now].cr=tree[now].s;
return;
}
int mid=(l+r)>>1;
build(l,mid,now<<1);
build(mid+1,r,now<<1|1);
pushup(now,now<<1,now<<1|1,l,r,mid);
}
void change(int l,int r,int now,int x,int y)
{
if(l==r)
{
tree[now].s=tree[now].m=tree[now].cl=tree[now].cr=y;
return;
}
int mid=(l+r)>>1;
if(x<=mid)
change(l,mid,now<<1,x,y);
else
change(mid+1,r,now<<1|1,x,y);
pushup(now,now<<1,now<<1|1,l,r,mid);
}
node add(node a,node b,int l,int r,int mid)
{
node c;
c.s=a.s+b.s;
c.m=max(a.m,max(b.m,a.cr+b.cl));
c.cl=max(a.cl,a.s+b.cl);
c.cr=max(b.cr,b.s+a.cr);
return c;
}
node query(int l,int r,int now,int x,int y)
{
if(x<=l&&r<=y)
return tree[now];
int mid=(l+r)>>1;
if(y<=mid)
return query(l,mid,now<<1,x,y);
else if(x>mid)
return query(mid+1,r,now<<1|1,x,y);
else
return add(query(l,mid,now<<1,x,y),query(mid+1,r,now<<1|1,x,y),x,y,mid);
}