线段树——区间最大连续字段和(acwing245)

题目链接

求区间的最大连续字段和,需要同时维护节点的sum(区间和),lsum(区间前缀和最大值),rsum(区间后缀的最大值),dat(最大字段和)。
ac代码:

#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 500005;
struct Node{
    int l,r;
    int sum;//区间和
    int lsum,rsum,dat;
}tr[4*N];
int n,m;
int a[N];

void pushup(int u){
    tr[u].sum = tr[u*2].sum + tr[u*2+1].sum;
    tr[u].lsum = max(tr[u*2].lsum,tr[u*2].sum+tr[u*2+1].lsum);
    tr[u].rsum = max(tr[u*2+1].rsum,tr[u*2].rsum + tr[u*2+1].sum);
    tr[u].dat = max(tr[2*u].rsum+tr[2*u+1].lsum,max(tr[2*u].dat,tr[2*u+1].dat));
}

void init(int u,int v){
    tr[u].sum = v;
    tr[u].lsum = v;
    tr[u].rsum = v;
    tr[u].dat = v;
}

void build(int u,int l,int r){
    tr[u].l = l;tr[u].r = r;
    if(l == r){
           init(u,a[l]);
    }else{
        int mid = l+r>>1;
        build(u*2,l,mid);
        build(u*2+1,mid+1,r);
        pushup(u);
    //    cout<<tr[u].l<<" "<<tr[u].r<<" "<<tr[u].dat<<endl;
    }
}

void update(int u,int x,int v){
    if(tr[u].l == tr[u].r){
        a[x] = v;
        init(u,v);
    }else{
        int mid = tr[u].l + tr[u].r >> 1;
        if(x<=mid)
            update(2*u,x,v);
        else
            update(2*u+1,x,v);
        pushup(u);
    }
}

Node query(int u,int l,int r){
    if(l<=tr[u].l && tr[u].r<=r){
        return tr[u];
    }else{
        int mid = tr[u].l + tr[u].r >>1;
        if(l>mid){
            return query(u*2+1,l,r);
        }else if(r<=mid){
            return query(u*2,l,r);
        }else{
            Node res;
            Node left = query(2*u,l,r);
            Node rigth = query(2*u+1,l,r);
            res.sum = left.sum + rigth.sum;
            res.lsum = max(left.lsum,left.sum+rigth.lsum);
            res.rsum = max(rigth.rsum,left.rsum + rigth.sum);
            res.dat = max(left.rsum+rigth.lsum,max(left.dat,rigth.dat));
            return res;
        }
    }
}

int main(){
    int i,j;
    cin>>n>>m;
    for(i = 1;i<=n;i++) cin>>a[i];
    build(1,1,n);
    for(i = 1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        if(a == 1){
            if(b>c) swap(b,c);
            cout<<query(1,b,c).dat<<endl;
        }else{
            update(1,b,c);
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值