线段树最大子段

简介: 线段树最大子段

线段树最大子段模板


struct node{
  int l,r;
  int sum,ms;//maxsum
    int ml,mr;//maxl,maxr
}tree[N*4];
void PushUp(int i)
{
  tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
  tree[i].ml=max(tree[i<<1].sum+tree[i<<1|1].ml,tree[i<<1].ml);
  tree[i].mr=max(tree[i<<1|1].sum+tree[i<<1].mr,tree[i<<1|1].mr);
  tree[i].ms=max(max(tree[i<<1].ms,tree[i<<1|1].ms),tree[i<<1].mr+tree[i<<1|1].ml);
}
void build(int i,int l,int r)
{
  tree[i].l=l,tree[i].r=r;
  if(l==r)
  {
    tree[i].sum=tree[i].ml=tree[i].mr=tree[i].ms=a[l];
    return ;
  }
  int mid=(l+r)>>1;
  build(i<<1,l,mid);
  build(i<<1|1,mid+1,r);
  PushUp(i);
}
void update(int i,int pos,int val)
{
  if(tree[i].l==tree[i].r)
  {
    tree[i].ms=tree[i].ml=tree[i].mr=tree[i].sum=val;
    return ;
  }
  int mid=(tree[i].l+tree[i].r)>>1;
  if(pos<=mid)
    update(i<<1,pos,val);
  else update(i<<1|1,pos,val);
  PushUp(i);
}
node query(int i,int l,int r)
{
  if(l<=tree[i].l&&tree[i].r<=r)
    return tree[i];
  int mid=(tree[i].l+tree[i].r)>>1;
  if(r<=mid) return query(i<<1,l,r);
  else if(l>mid) return query(i<<1|1,l,r);
  else
  {
    node x=query(i<<1,l,r),y=query(i<<1|1,l,r),res;
    //合并答案 
    res.sum=x.sum+y.sum;
    res.ml=max(x.sum+y.ml,x.ml);
    res.mr=max(y.sum+x.mr,y.mr);
    res.ms=max(max(x.ms,y.ms),x.mr+y.ml);
    return res;
  }
}

参考

相关文章
|
8天前
线段树(连载中)
线段树(连载中)
16 0
|
6月前
|
C++
线段树的区间修改
线段树的区间修改
23 0
|
8天前
|
算法 测试技术 C++
|
8天前
|
索引 NoSQL 容器
树状数组与线段树
树状数组与线段树
|
9月前
初识线段树
初识线段树
30 0
|
11月前
|
存储 算法 Java
线段树SegmentTree
线段树SegmentTree
|
算法
一道线段树相关算法题
每个方块都从一个比目前所有的落地方块更高的高度掉落而下。方块沿 y 轴负方向下落,直到着陆到 另一个正方形的顶边 或者是 x 轴上 。一个方块仅仅是擦过另一个方块的左侧边或右侧边不算着陆。一旦着陆,它就会固定在原地,无法移动。
68 0
一道线段树相关算法题