【题目】

给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:
“1 x y”,查询区间 [x,y] 中的最大连续子段和,即

“2 x y”,把 A[x] 改成 y。

对于每个查询指令,输出一个整数表示答案

【题解】

刚开始看的时候,单点更新,区间修改,第一反应就是线段树,但问题就出在求最大连续子段和,这是个麻烦的事情。而解决这个的方法,就是在线段树中放四个值是指在线段树的这个区间内,所有数的和,指的是这个区间内从最左边开始连续的最大子段和,指的是这个区间内从最右边开始的最大子段和,则指的是这个区间内中间最大子段和(跟不同的地方就在于可以不是从极端开始连续)。这么设计线段树,是因为线段树本身具有的特性形成的,从线段树的最底层想想看,是不是每次跟左兄弟姐妹和右兄弟姐妹的合并:

都是,进而的求出的最优值,
又都是,进而的求出的最优值,
又都是,进而的求出的最优值。

那么到了最后,是不是整个线段树的所有的区间只要就能找到这个区间的最大值。当然查询的过程中,还是需要合并被分开来的区间的,这个的话,可以看看我的线段树查询代码。还有就是因为是单点更新,所以不需要懒标记。

时间复杂度:线段树的建树复杂度,查询复杂度,更新复杂度,此题整体复杂度

#include<iostream>
#include<cstring>
#include<sstream>
#include<string>
#include<cstdio>
#include<cctype>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#define fi first
#define se second
#define MP make_pair
#define P pair<int,int>
#define PLL pair<ll,ll>
#define Sca(x) scanf("%d",&x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%ld",&x)
#define Scll(x) scanf("%lld",&x)
#define Pri(x) printf("%d\n",x);
#define Prl(x) printf("%lld\n",x);
#define For(i,x,y) for(int i=x;i<=y;i++)
#define _For(i,x,y) for(int i=x;i>=y;i--)
#define FAST_IO std::ios::sync_with_stdio(false)
#define ll long long
const int INF=0x3f3f3f3f;
const ll INFL=0x3f3f3f3f3f3f3f3f;
const double Pi = acos(-1.0);
using namespace std;
template <class T>void tomax(T&a,T b){ a=max(a,b); } 
template <class T>void tomin(T&a,T b){ a=min(a,b); }
const int N=5e5+5;
struct SEG{
    struct Tree{
        int l,r;
        int ans,lmax,rmax,dat;
    }tree[N<<2];
    #define lc (p<<1)
    #define rc ((p<<1)|1)
    #define MID (tree[p].l+tree[p].r)>>1
    void pushup(int p){
        tree[p].ans=tree[lc].ans+tree[rc].ans;
        tree[p].lmax=max(tree[lc].lmax,tree[lc].ans+tree[rc].lmax);
        tree[p].rmax=max(tree[rc].rmax,tree[rc].ans+tree[lc].rmax);
        tree[p].dat=max(tree[lc].dat,max(tree[rc].dat,tree[lc].rmax+tree[rc].lmax));
    }
    void build(int l,int r,int p){
        tree[p].l=l;
        tree[p].r=r;
        tree[p].ans=0;
        if(l==r){
            int x; Sca(x);
            tree[p].ans=tree[p].lmax=tree[p].rmax=tree[p].dat=x;
            return ;
        }
        int mid=MID;
        build(l,mid,lc);
        build(mid+1,r,rc);
        pushup(p);
    }
    void updata(int id,int p,int val){
        if(tree[p].l==id&&tree[p].r==id){
            tree[p].ans=tree[p].lmax=tree[p].rmax=tree[p].dat=val;
            return ;
        }
        int mid=MID;
        if(id<=mid) updata(id,lc,val);
        else updata(id,rc,val);
        pushup(p);
    }
    Tree query(int l,int r,int p){
        if(tree[p].l>=l&&tree[p].r<=r){
            return tree[p];
        }
        int mid=MID;
        if(r<=mid) return query(l,r,lc);
        else if(l>mid) return query(l,r,rc);
        else{
            Tree x,t1=query(l,r,lc),t2=query(l,r,rc);
            x.lmax=max(t1.lmax,t1.ans+t2.lmax);
            x.rmax=max(t2.rmax,t2.ans+t1.rmax);
            x.dat=max(t1.dat,max(t2.dat,t1.rmax+t2.lmax));
            return x;
        }
    }
    int get(int l,int r){
        Tree now=query(l,r,1);
        int maxx=now.lmax;
        tomax(maxx,now.rmax);
        tomax(maxx,now.dat);
        return maxx;
    }
};
SEG go;
int main(){
    int n,m; Sca2(n,m);
    go.build(1,n,1);
    while(m--){
        int op,x,y; Sca3(op,x,y);
        if(op==1){
            if(x>y) swap(x,y);
            Pri(go.get(x,y));
        }
        else go.updata(x,1,y);
    }
}