#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ls u<<1
#define rs u<<1|1
const int N=500010;
int n,m,a[N];
struct Tree{ //线段树
int l,r;
//区间和,最大左子段和,最大右子段和,最大子段和
int sum,lmx,rmx,mx;
}tr[N*4];
void pushup(Tree &u,Tree l,Tree r){
u.sum=l.sum+r.sum;
u.lmx=max(l.lmx, l.sum+r.lmx);
u.rmx=max(r.rmx, r.sum+l.rmx);
u.mx=max(max(l.mx, r.mx), l.rmx+r.lmx);
}
void build(int u,int l,int r){ //建树
tr[u]={l,r,a[r],a[r],a[r],a[r]};
if(l==r) return;
int m=l+r>>1;
build(ls,l,m);
build(rs,m+1,r);
pushup(tr[u],tr[ls],tr[rs]);
}
void change(int u,int x,int v){ //点修
if(tr[u].l==tr[u].r){
tr[u]={x,x,v,v,v,v};
return;
}
int m=tr[u].l+tr[u].r>>1;
if(x<=m) change(ls,x,v);
else change(rs,x,v);
pushup(tr[u],tr[ls],tr[rs]);
}
Tree query(int u,int x,int y){ //区查
if(x<=tr[u].l && tr[u].r<=y) return tr[u];
int m=tr[u].l+tr[u].r>>1;
if(y<=m) return query(ls,x,y);
if(x>m) return query(rs,x,y);
Tree T; //开一个临时节点,存储拼凑结果
pushup(T,query(ls,x,m),query(rs,m+1,y));
return T;
}
// Tree query(int u,int x,int y){ //区查
// if(x>tr[u].r||y<tr[u].l)
// return {tr[u].l,tr[u].r,0,-1e9,-1e9,-1e9};
// if(x<=tr[u].l && tr[u].r<=y) return tr[u];
// Tree T; //开一个临时节点,存储拼凑结果
// pushup(T,query(ls,x,y),query(rs,x,y));
// return T;
// }
int main(){
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
build(1,1,n);
while(m--){
int k,x,y; scanf("%d%d%d",&k,&x,&y);
if(k==1){
if(x>y) swap(x,y);
printf("%d\n",query(1,x,y).mx);
}
else change(1,x,y);
}
return 0;
}
注意这里,新开了一个T来存储。比如要查询3到8的和,先查到区间[3,3]然后就往上递归把9号点信息给到4号点再给到2号,然后又去查【4,5】
然后此时要递归回到2号节点,然后就要通过pushup和刚刚存9号节点过来的信息进行拼凑