传送门
首先
c
x
=
m
a
x
0
≤
i
≤
x
{
a
[
i
]
+
s
u
m
[
x
]
−
s
u
m
[
i
]
}
=
s
u
m
[
x
]
+
m
a
x
0
≤
i
≤
x
{
a
[
i
]
−
s
u
m
[
i
]
}
c_x=max_{0\le i\le x}\{a[i]+sum[x]-sum[i]\}=sum[x]+max_{0\le i\le x}\{a[i]-sum[i]\}
cx=max0≤i≤x{a[i]+sum[x]−sum[i]}=sum[x]+max0≤i≤x{a[i]−sum[i]},于是用线段树考虑维护
a
[
i
]
−
s
u
m
[
i
]
a[i]-sum[i]
a[i]−sum[i]这个值即可,第一个操作对应修改
a
[
x
]
a[x]
a[x],是单点修改,第二个操作对应修改
s
u
m
[
x
∼
n
]
sum[x\sim n]
sum[x∼n],是区间修改,第三个操作是查询
a
[
i
]
−
s
u
m
[
i
]
a[i]-sum[i]
a[i]−sum[i]在区间
x
∼
n
x\sim n
x∼n上的最大值,这三个操作都很好用线段树维护。
int a[maxn],b[maxn];
ll t[maxn<<2],sum[maxn],lz[maxn<<2];
void pushup(int rt){
t[rt]=max(t[rt<<1],t[rt<<1|1]);
}
void pushdown(int rt){
if(lz[rt]){
lz[rt<<1]+=lz[rt];
lz[rt<<1|1]+=lz[rt];
t[rt<<1]+=lz[rt];
t[rt<<1|1]+=lz[rt];
lz[rt]=0;
}
}
void build(int rt,int l,int r){
lz[rt]=0;
if(l==r){
t[rt]=a[l]-sum[l];
return ;
}
int mid=l+r>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void cg(int rt,int l,int r,int ql,int qr,int ad){
if(l>=ql && r<=qr){
t[rt]+=ad;
lz[rt]+=ad;
return;
}
pushdown(rt);
int mid=l+r>>1;
if(l<=qr && mid>=ql)cg(rt<<1,l,mid,ql,qr,ad);
if(mid+1<=qr && r>=ql)cg(rt<<1|1,mid+1,r,ql,qr,ad);
pushup(rt);
}
ll qry(int rt,int l,int r,int ql,int qr){
if(l>=ql && r<=qr){
return t[rt];
}
int mid=l+r>>1;
pushdown(rt);
ll ans=-INF;
if(l<=qr && mid>=ql)ans=qry(rt<<1,l,mid,ql,qr);
if(mid+1<=qr && r>=ql)ans=max(ans,qry(rt<<1|1,mid+1,r,ql,qr));
pushup(rt);
return ans;
}
int main(){
int n=rd(),m=rd();
while(n && m){
FOR(i,1,n+1)a[i]=rd();
FOR(i,1,n+1){
b[i]=rd();
sum[i]=sum[i-1]+b[i];
}
build(1,1,n);
while(m--){
int op=rd(),x,y;
if(op==1){
x=rd(),y=rd();
cg(1,1,n,x,x,y-a[x]);
a[x]=y;
}else if(op==2){
x=rd(),y=rd();
cg(1,1,n,x,n,b[x]-y);
b[x]=y;
}else if(op==3){
x=rd();
wrn(a[x]-qry(1,1,n,x,x)+max(0ll,qry(1,1,n,1,x)));
}
}
n=rd(),m=rd();
}
}