求区间的最大连续字段和,需要同时维护节点的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;
}