因为是区间查询,我们用线段树维护
为了求最大子段和(mfa),有几种情况?
将一个区间分成L,R
最大子段和在LR中间
可以看到,这种情况下的最大字段和由两部分——L最大后缀和(suf)和R最大前缀和(pre)构成
所以得出 x . m f a = m a x { l c . m f a , r c . m f a , l c . s u f + r c . p r e } x.mfa=max\{lc.mfa,rc.mfa,lc.suf+rc.pre\} x.mfa=max{lc.mfa,rc.mfa,lc.suf+rc.pre}
所以,我们现在要维护的多了suf和pre
来看看求pre的情况
L的全部和R
由此我们得出 x . p r e = m a x { l c . p r e , l c . s u m + r c . p r e } x.pre=max\{lc.pre,lc.sum+rc.pre\} x.pre=max{lc.pre,lc.sum+rc.pre}
同样地,我们也可以得出 x . s u f = m a x { r c . s u f , l c . s u f + r c . s u m } x.suf=max\{rc.suf,lc.suf+rc.sum\} x.suf=max{rc.suf,lc.suf+rc.sum}
至此,我们得出需要维护的有四个: m f a , s u f , p r e , s u m mfa,suf,pre,sum mfa,suf,pre,sum
用结构体存一下
理论存在,实践开始
#include
using namespace std;
const int M = 1e5+10;
int a[M],n,m;
struct node{
int mfa,pre,suf,sum;
};
struct segment{
#define rc ((x<<1)|1)//左右结点
#define lc (x<<1)
node seg[M<<2];
void pushup(int x){//需要维护的
seg[x].sum=seg[lc].sum+seg[rc].sum;//区间和
seg[x].pre=max(seg[lc].pre,seg[lc].sum+seg[rc].pre);//最大前缀和
seg[x].suf=max(seg[rc].suf,seg[rc].sum+seg[lc].suf);//最大后缀和
seg[x].mfa=max(max(seg[lc].mfa,seg[rc].mfa),seg[lc].suf+seg[rc].pre);//最大子段和
}
void build(int x,int l,int r){//建树
if(l==r){
seg[x].mfa=seg[x].pre=seg[x].suf=seg[x].sum=a[l];
return;
}
int mid=l+r>>1;
build(lc,l,mid),build(rc,mid+1,r);
pushup(x);
}
void update(int x,int l,int r,int o,int k){//修改操作
if(l==r&&l==o){
seg[x].mfa=seg[x].pre=seg[x].suf=seg[x].sum=k;
return;
}
if(o<l||r<o) return;
int mid=l+r>>1;
update(lc,l,mid,o,k),update(rc,mid+1,r,o,k);
pushup(x);
}
node query(int x,int ql,int qr,int l,int r){//查询操作
if(ql<=l&&r<=qr) return seg[x];
bool f1=0,f2=0;
node left,right;
int mid=l+r>>1;
if(ql<=mid) left=query(lc,ql,qr,l,mid),f1=1;
if(mid+1<=qr) right=query(rc,ql,qr,mid+1,r),f2=1;
node ans;
if(f1&&f2){//如果L,R内都有
ans.sum=left.sum+right.sum;
ans.pre=max(left.pre,left.sum+right.pre);
ans.suf=max(right.suf,right.sum+left.suf);
ans.mfa=max(max(left.mfa,right.mfa),left.suf+right.pre);
}
else if(f1) ans=left;
else ans=right;
return ans;
}
}T;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>m;
T.build(1,1,n);
while(m--){
int if_case;
cin>>if_case;
int x,y;
cin>>x>>y;
switch (if_case){
case 1:cout<<T.query(1,x,y,1,n).mfa<<endl;break;
case 0:T.update(1,1,n,x,y);break;
}
}
return 0;
}