传送门
解析:
序列问题考虑线段树,考虑合并两个区间,显然新的答案是两个区间的答案和两个区间前后缀最大值拼起来的答案。
为了更新前后缀最大值需要维护一下区间和。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
re bool f=0;
while(!isdigit(c=gc()))f^=c=='-';re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
}
using namespace IO;
inline int max(int a,int b){return a<b?b:a;}
cs int N=5e4+4;
struct node{
int lmx,rmx,mx,sum;
node(){}
friend node operator+(cs node &l,cs node &r){
node t;
t.sum=l.sum+r.sum;
t.lmx=max(l.lmx,r.lmx+l.sum);
t.rmx=max(r.rmx,l.rmx+r.sum);
t.mx=max(max(l.mx,r.mx),l.rmx+r.lmx);
return t;
}
}t[N<<2];
inline void build(int k,int l,int r){
if(l==r){
t[k].lmx=t[k].rmx=t[k].mx=t[k].sum=getint();
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
t[k]=t[k<<1]+t[k<<1|1];
}
inline void modify(int k,int l,int r,cs int &pos){
if(l==r){
t[k].lmx=t[k].rmx=t[k].mx=t[k].sum=getint();
return ;
}
int mid=(l+r)>>1;
if(pos<=mid)modify(k<<1,l,mid,pos);
else modify(k<<1|1,mid+1,r,pos);
t[k]=t[k<<1]+t[k<<1|1];
}
inline node query(int k,int l,int r,cs int &ql,cs int &qr){
if(ql<=l&&r<=qr)return t[k];
int mid=(l+r)>>1;
if(qr<=mid)return query(k<<1,l,mid,ql,qr);
if(mid<ql)return query(k<<1|1,mid+1,r,ql,qr);
return query(k<<1,l,mid,ql,qr)+query(k<<1|1,mid+1,r,ql,qr);
}
int n,q;
signed main(){
n=getint();
build(1,1,n);
q=getint();
std::ios::sync_with_stdio(false);
while(q--)switch(getint()){
case 0:{
modify(1,1,n,getint());
break;
}
case 1:{
int l=getint(),r=getint();
std::cout<<query(1,1,n,l,r).mx<<"\n";
break;
}
}
return 0;
}