题意: 维护数据结构,支持区间赋值,查询区间最大字段和
线段树
我们一个点存4个值
L_Max 表示从左端点开始的最大字段和
R_Max 表示从右端点开始的最大字段和
Max 表示区间的最大字段和
val 表示区间和
考虑如何更新
我们发现对于任何一个节点的Max, 要么全取右子树,要么全取左子树,要么一个取一点
L_Max 要么还是取右子树,要么取右子树全部,再加上左子树的L_Max
R_Max 同理
void Pushup(int x){
t[x].Max=max(max(t[x<<1].Max , t[x<<1|1].Max) , t[x<<1].R_Max + t[x<<1|1].L_Max);
t[x].L_Max=max(t[x<<1].L_Max , t[x<<1].val + t[x<<1|1].L_Max);
t[x].R_Max=max(t[x<<1|1].R_Max , t[x<<1|1].val + t[x<<1].R_Max);
t[x].val = t[x<<1].val + t[x<<1|1].val;
}
查询也同理
void quary(int o,int L,int R,int &ans,int &Lans,int &Rans){
if(L<=t[o].l&&t[o].r<=R){
ans=t[o].Max; Lans=t[o].L_Max; Rans=t[o].R_Max; return;
}
int mid=(t[o].r+t[o].l)>>1;
if(R<=mid) quary(o<<1,L,R,ans,Lans,Rans);//全左
else if(L>mid) quary(o<<1|1,L,R,ans,Lans,Rans);//全右
else{//两边都有
int L_ans,L_lans, L_rans, R_ans, R_lans, R_rans;
L_ans = L_lans = L_rans = R_ans = R_lans = R_rans = 0;
quary(o<<1,L,R,L_ans,L_lans,L_rans);
quary(o<<1|1,L,R,R_ans,R_lans,R_rans);
ans=max(max(L_ans , R_ans) , L_rans + R_lans);
Lans=max(Lans , t[o<<1].val + R_lans);
Rans=max(Rans , t[o<<1|1].val + L_rans);
}
}
区间赋值打tag就可以了
代码
//区间赋值,区间最大字段和
#include<bits/stdc++.h>
#define N 100005
#define Len (t[o].r-t[o].l+1)
#define lLen (t[o<<1].r-t[o<<1].l+1)
#define rLen (t[o<<1|1].r-t[o<<1|1].l+1)
using namespace std;
struct Node{
int l,r,val,Max,L_Max,R_Max,tag;
}t[N<<2];
int n,m,a[N],Ans,LA,RA;
int read(){
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
return cnt*f;
}
void Pushup(int x){
t[x].Max=max(max(t[x<<1].Max , t[x<<1|1].Max) , t[x<<1].R_Max + t[x<<1|1].L_Max);
t[x].L_Max=max(t[x<<1].L_Max , t[x<<1].val + t[x<<1|1].L_Max);
t[x].R_Max=max(t[x<<1|1].R_Max , t[x<<1|1].val + t[x<<1].R_Max);
t[x].val = t[x<<1].val + t[x<<1|1].val;
}
void Pushdown(int o){
if(t[o].tag){
if(t[o].tag>0){
t[o<<1].Max = t[o<<1].L_Max = t[o<<1].R_Max = t[o].tag * lLen;
t[o<<1|1].Max = t[o<<1|1].L_Max = t[o<<1|1].R_Max = t[o].tag * rLen;
}
else{
t[o<<1].Max = t[o<<1].L_Max = t[o<<1].R_Max = t[o].tag;
t[o<<1|1].Max = t[o<<1|1].L_Max = t[o<<1|1].R_Max = t[o].tag;
}
t[o<<1].val = t[o].tag * lLen; t[o<<1].tag+=t[o].tag;
t[o<<1|1].val = t[o].tag * rLen; t[o<<1|1].tag+=t[o].tag;
t[o].tag=0;
}
}
void build(int o,int l,int r){
t[o].l=l,t[o].r=r;
if(l==r){t[o].Max=t[o].L_Max=t[o].R_Max=t[o].val=a[l];return;}
int mid=(l+r)>>1;
build(o<<1,l,mid),build(o<<1|1,mid+1,r);
Pushup(o);
}
void update(int o,int L,int R,int val){
if(L<=t[o].l&&t[o].r<=R){
t[o].Max = t[o].L_Max = t[o].R_Max = val<0 ? val : val * Len;
t[o].val = val*Len; t[o].tag+=val;
return;
}
Pushdown(o);
int mid=(t[o].l+t[o].r)>>1;
if(L<=mid) update(o<<1,L,R,val);
if(R>mid) update(o<<1|1,L,R,val);
Pushup(o);
}
void quary(int o,int L,int R,int &ans,int &Lans,int &Rans){
if(L<=t[o].l&&t[o].r<=R){
ans=t[o].Max; Lans=t[o].L_Max; Rans=t[o].R_Max; return;
}
int mid=(t[o].r+t[o].l)>>1;
if(R<=mid) quary(o<<1,L,R,ans,Lans,Rans);
else if(L>mid) quary(o<<1|1,L,R,ans,Lans,Rans);
else{
int L_ans,L_lans, L_rans, R_ans, R_lans, R_rans;
L_ans = L_lans = L_rans = R_ans = R_lans = R_rans = 0;
quary(o<<1,L,R,L_ans,L_lans,L_rans);
quary(o<<1|1,L,R,R_ans,R_lans,R_rans);
ans=max(max(L_ans , R_ans) , L_rans + R_lans);
Lans=max(Lans , t[o<<1].val + R_lans);
Rans=max(Rans , t[o<<1|1].val + L_rans);
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++) a[i]=read();
build(1,1,n);
while(m--){
int op=read(),x=read(),y=read();
if(op==1){int val=read();update(1,x,y,val);}
else{quary(1,x,y,Ans,LA,RA);printf("%d\n",Ans);Ans=LA=RA=0;}
}
}