【vijos1083】小白逛公园
描述
小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。
一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第a个和第b个公园之间(包括a、b两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。
那么,就请你来帮小白选择公园吧。
输入格式
第一行,两个整数N和M,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来N行,每行一个整数,依次给出小白 开始时对公园的打分。
接下来M行,每行三个整数。第一个整数K,1或2。K=1表示,小新要带小白出去玩,接下来的两个整数a和b给出了选择公园的范围(1≤a,b≤N, a可以大于b!);K=2表示,小白改变了对某个公园的打分,接下来的两个整数p和s,表示小白对第p个公园的打分变成了s(1≤p≤N)。
其中,1≤N≤500 000,1≤M≤100 000,所有打分都是绝对值不超过1000的整数。
输出格式
小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。
分析:裸的线段树维护区间和,可以拿来做模板,注意tr有4个标记,ml表示从左端开始的最大和,mr是从右端开始的最大字段和,mx是区间中的最大连续字段和,sum是区间和,然后不难看出这样维护:
sum[h] = sum[h << 1] + sum[h << 1|1];
ml[h]= max(ml[h<<1],sum[h<<1]+ml[h<<1|1]);
mr[h]=max(mr[h<<1|1],sum[<<1|1]+mr[h<<1]; mx[h]=max(max(mx[h<<1],mx[h<<1|1]),ml[h<<1|1]+mr[h<<1]);
# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <queue>
# include <cmath>
# include <vector>
using namespace std;
int read(){
register int f=1,i=0;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}
return f*i;
}
const int N=2000000+10;
struct node{
int ml,mr,mx,sum;
node(){};
node(int ml,int mr,int mx,int sum) : ml(ml),mr(mr),mx(mx),sum(sum){}
}tr[N];
int n,m,x,y,z,k,a[N];
struct seg{
inline void change(int k){
tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
tr[k].ml=max(tr[k<<1].ml,tr[k<<1].sum+tr[k<<1|1].ml);
tr[k].mr=max(tr[k<<1|1].mr,tr[k<<1|1].sum+tr[k<<1].mr);
tr[k].mx=max(max(tr[k<<1].mx,tr[k<<1|1].mx),tr[k<<1].mr+tr[k<<1|1].ml);
}
inline void build(int k,int l,int r){
if(l==r){
tr[k].sum=tr[k].mx=tr[k].ml=tr[k].mr=a[l];
return;
}
int mid=l+r>>1;
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
change(k);
}
inline void update(int k,int l,int r,int pos,int x){
if(l==r){
tr[k].sum=tr[k].mx=tr[k].ml=tr[k].mr=x;
return;
}
int mid=l+r>>1;
if(pos<=mid) update(k<<1,l,mid,pos,x);
if(pos>mid) update(k<<1|1,mid+1,r,pos,x);
change(k);
}
node query(int k,int l,int r,int s,int t){
if(s==l&&r==t){
node tmp=node(tr[k].ml,tr[k].mr,tr[k].mx,tr[k].sum);
return tmp;
}
int mid=l+r>>1;
if(t<=mid) return query(k<<1,l,mid,s,t);
else if(s>mid) return query(k<<1|1,mid+1,r,s,t);
node a,b,tmp;
a=query(k<<1,l,mid,s,mid);
b=query(k<<1|1,mid+1,r,mid+1,t);
tmp.mx=max(max(a.mx,b.mx),a.mr+b.ml);
tmp.ml=max(a.ml,a.sum+b.ml);
tmp.mr=max(b.mr,b.sum+a.mr);
return tmp;
}
}Seg;
int main(){
freopen("lx.in","r",stdin);
n=read(),m=read();
for(int i=1;i<=n;++i) a[i]=read();
Seg.build(1,1,n);
for(int i=1;i<=m;++i){
k=read();
if(k==1){
x=read(),y=read();
if(x > y)swap(x,y);
printf("%d\n",Seg.query(1,1,n,x,y).mx);
}else{
x=read(),y=read();
Seg.update(1,1,n,x,y);
}
}
}