题意:两种操作,一是单点修改,二是查询区间最大子段和.
操作一是常规操作,对于操作二,线段树上我们要维护每个节点(区间)的最大左子段和,最大右子段和,最大子段和,以及区间和四个东西.
然后更新就是:
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
t[p].lmax=max(t[p<<1].lmax,t[p<<1].sum+t[p<<1|1].lmax);
t[p].rmax=max(t[p<<1|1].rmax,t[p<<1|1].sum+t[p<<1].rmax);
t[p].data=max(t[p<<1].data,max(t[p<<1|1].data,t[p<<1].rmax+t[p<<1|1].lmax));
查询的话,一个区间的最大子段和,同更新类似,会有多种来源,可能是左子区间的最大左子段和,右子区间的最大右子段和,左子区间的最大右子段和加上右子区间的最大左子段和.都要考虑到.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=500005;
int n,m,val[N];
struct XD_Tree{int l,r,lmax,rmax,sum,data;}t[N<<2];
inline void build(int p,int l,int r){
t[p].l=l;t[p].r=r;
if(l==r){
t[p].lmax=t[p].rmax=t[p].sum=t[p].data=val[l];
return;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
t[p].lmax=max(t[p<<1].lmax,t[p<<1].sum+t[p<<1|1].lmax);
t[p].rmax=max(t[p<<1|1].rmax,t[p<<1|1].sum+t[p<<1].rmax);
t[p].data=max(t[p<<1].data,max(t[p<<1|1].data,t[p<<1].rmax+t[p<<1|1].lmax));
}
inline void change(int p,int pos,int v){
if(t[p].l==t[p].r){
t[p].lmax=t[p].rmax=t[p].sum=t[p].data=v;
return;
}
int mid=(t[p].l+t[p].r)>>1;
if(pos<=mid)change(p<<1,pos,v);
else change(p<<1|1,pos,v);
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
t[p].lmax=max(t[p<<1].lmax,t[p<<1].sum+t[p<<1|1].lmax);
t[p].rmax=max(t[p<<1|1].rmax,t[p<<1|1].sum+t[p<<1].rmax);
t[p].data=max(t[p<<1].data,max(t[p<<1|1].data,t[p<<1].rmax+t[p<<1|1].lmax));
}
inline XD_Tree query(int p,int ql,int qr){
int l=t[p].l,r=t[p].r;
if(ql<=l&&qr>=r)return t[p];
int mid=(l+r)>>1;XD_Tree a,b,c;
a.data=a.sum=a.lmax=a.rmax=-1e9;
b.data=b.sum=b.lmax=b.rmax=-1e9;
c.sum=0;
if(ql<=mid){
a=query(p<<1,ql,qr);
c.sum+=a.sum;
}
if(qr>mid){
b=query(p<<1|1,ql,qr);
c.sum+=b.sum;
}
c.data=max(max(a.data,b.data),a.rmax+b.lmax);
c.lmax=max(a.lmax,b.lmax+a.sum);
if(ql>mid)c.lmax=max(c.lmax,b.lmax);
c.rmax=max(b.rmax,b.sum+a.rmax);
if(qr<=mid)c.rmax=max(c.rmax,a.rmax);
return c;
}
int main(){
n=read();m=read();
for(int i=1;i<=n;++i)val[i]=read();
build(1,1,n);
while(m--){
int opt=read(),x=read(),y=read();
if(opt==1){
if(x>y)swap(x,y);
printf("%d
",query(1,x,y).data);
}
else change(1,x,y);
}
return 0;
}