线段树维护最大字段和

题意: 维护数据结构,支持区间赋值,查询区间最大字段和


线段树

我们一个点存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;}
	} 
}

猜你喜欢

转载自blog.csdn.net/sslz_fsy/article/details/82988022