传送门
线段树常规操作了解一下。
单点修改维护区间最大连续和。
对于一个区间,维护区间从左端点开始的连续最大和,从右端点开始的连续最大和,整个区间最大和,区间和。
代码如下:
#include<bits/stdc++.h>
#define N 500005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
struct Node{int l,r,ls,rs,ms,sum;}T[N<<2];
int n,m,a[N];
inline int max(int a,int b){return a>b?a:b;}
inline void pushup(int p){
T[p].sum=T[lc].sum+T[rc].sum;
T[p].ls=max(T[lc].ls,T[lc].sum+T[rc].ls);
T[p].rs=max(T[rc].rs,T[rc].sum+T[lc].rs);
T[p].ms=max(max(T[lc].ms,T[rc].ms),T[lc].rs+T[rc].ls);
}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r;
if(l==r){T[p].ls=T[p].rs=T[p].ms=T[p].sum=a[l];return;}
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
}
inline void update(int p,int k,int v){
if(T[p].l==T[p].r){
T[p].ls=T[p].rs=T[p].ms=T[p].sum=v;
return;
}
if(k<=mid)update(lc,k,v);
else update(rc,k,v);
pushup(p);
}
inline Node query(int p,int ql,int qr){
if(ql<=T[p].l&&T[p].r<=qr)return T[p];
if(qr<=mid)return query(lc,ql,qr);
if(ql>mid)return query(rc,ql,qr);
Node ans1=query(lc,ql,mid),ans2=query(rc,mid+1,qr),ans;
ans.l=ans1.l,ans.r=ans2.r;
ans.ls=max(ans1.ls,ans1.sum+ans2.ls);
ans.rs=max(ans2.rs,ans2.sum+ans1.rs);
ans.ms=max(max(ans1.ms,ans2.ms),ans1.rs+ans2.ls);
ans.sum=ans1.sum+ans2.sum;
return ans;
}
inline int read(){
int ans=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans*w;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i)a[i]=read();
build(1,1,n);
while(m--){
int op=read(),a=read(),b=read();
switch(op){
case 1:{if(a>b)a^=b,b^=a,a^=b;printf("%d\n",query(1,a,b).ms);break;}
default:{update(1,a,b);break;}
}
}
return 0;
}