线段树—最大字段和

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=5e5+10;
typedef long long ll;
int n,m;
struct node{
    ll ls,rs,ms,s;
}a[maxn<<2];

int A[maxn];

void pushup(int rt){
    int lson=rt<<1;
    int rson=rt<<1|1;
    a[rt].s=a[lson].s+a[rson].s;
    a[rt].ls=max(a[lson].ls , a[lson].s+a[rson].ls);
    a[rt].rs=max(a[rson].rs , a[rson].s+a[lson].rs);
    a[rt].ms=max(max(a[lson].ms,a[rson].ms),a[lson].rs+a[rson].ls);
}

void build(int l,int r,int rt){
    if(l==r){
        a[rt].ls=a[rt].rs=a[rt].ms=a[rt].s=A[l];
        return;
    }
    int m=l+r>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushup(rt);
}

void update(int pos,int val,int l,int r,int rt){
    if(l==r){
        a[rt].ls=a[rt].rs=a[rt].ms=a[rt].s=val;
        return;
    }
    int m=l+r>>1;
    if(pos<=m)
        update(pos,val,l,m,rt<<1);
    else
        update(pos,val,m+1,r,rt<<1|1);
    pushup(rt);
}

node query(int L,int R,int l,int r,int rt){//查询 L 到 R 区间内的最大字段和
    if(L<=l&&r<=R){
        return a[rt];
    }
    int m=l+r>>1;
    node ans,f1,f2;
    ans.s=0;
    if(R<=m)
        ans=query(L,R,l,m,rt<<1);
    if(L>m)
        ans=query(L,R,m+1,r,rt<<1|1);
    if(L<=m&&R>m){
        f1=query(L,R,l,m,rt<<1);
        f2=query(L,R,m+1,r,rt<<1|1);
        
        ans.s=f1.s+f2.s;
        ans.ls=max(f1.ls,f1.s+f2.ls);
        ans.rs=max(f2.rs,f2.s+f1.rs);
        ans.ms=max( max(f1.ms ,f2.ms) , f1.rs+f2.ls );
    }
    return ans;
}

void check(){
    for(int i=1;i<=9;i++)
        cout<<a[i].s<<" ";
    cout<<endl;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>A[i];
    build(1,n,1);
    //check();
    int A,B,C;
    for(int i=1;i<=m;i++){
        cin>>A>>B>>C;
        if(A==1){
            if (B>C) swap(B,C);
            cout<<query(B,C,1,n,1).ms<<'\n';
        }
        else
            update(B,C,1,n,1);
    }
    return 0;
}
posted @ 2020-01-02 16:27  艾尔夏尔-Layton  阅读(107)  评论(0编辑  收藏  举报