最大子段和之单点修改,区间查询
单点修改,区间查询的最大子段和
题目模型
-
我们对问题进行扩展,如果对序列有两种操作:
- 修改序列的某个元素的值
- 查询序列\([l,r]\)的区间和。
-
题目模型见P4513 小白逛公园
问题分析
- 单点修改,区间查询显然要用线段树。
- 类似上面分治,区间最大字段和有三种情况:
- 最大子段和在左子树。
- 最大子段和在右子树。
- 左子树的最大后缀和+右子树的最大前缀和。
代码实现
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+10;
#define lson l,mid,(rt<<1)
#define rson mid+1,r,(rt<<1|1)
struct Tree{
int presum,sufsum,sub,sum;//presum为当前区间最大前缀和,sufsum为当前区间最大后缀和,sub为当前区间最大子段和,sum为当前区间的和
}tree[maxn<<2];
Tree pushup(Tree l,Tree r){//合并左右两区间
Tree rt;
rt.presum=max(l.presum,l.sum+r.presum);//当前区间的最大前缀和:左子树的最大前缀和 or 左子树的和+右子树的最大前缀和
rt.sufsum=max(r.sufsum,r.sum+l.sufsum);//当前区间的最大后缀和:右子树的最大后缀和 or 右子树的和+左子树的最大后缀和
rt.sub=max(max(l.sub,r.sub),l.sufsum+r.presum);//当前区间的最大子段和:左子树的最大子段和 or 右子树的最大子段和 or 左子树的最大后缀和+右子树的最大前缀和
rt.sum=l.sum+r.sum;//当前区间的和:左子树的和+右子树的和
return rt;
}
void build(int l,int r,int rt){
if(l==r){
scanf("%d",&tree[rt].sum);
tree[rt].presum=tree[rt].sufsum=tree[rt].sub=tree[rt].sum;
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
tree[rt]=pushup(tree[rt<<1],tree[rt<<1|1]);
}
void update(int pos,int w,int l,int r,int rt){//把pos个元素修改成值w
if(l==r){
tree[rt].presum=tree[rt].sufsum=tree[rt].sub=tree[rt].sum=w;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) update(pos,w,lson);
if(pos> mid) update(pos,w,rson);
tree[rt]=pushup(tree[rt<<1],tree[rt<<1|1]);
}
Tree query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R)
return tree[rt];
int mid=(l+r)>>1;
Tree ret,lret,rret;
int flag1=0,flag2=0;//flag1标记区间[L,R]是否在rt的左子树,flag2右子树
if(L<=mid) {lret=query(L,R,lson);flag1=1;}
if(R> mid) {rret=query(L,R,rson);flag2=1;}
if(flag1&&flag2) ret=pushup(lret,rret);//左右子树均有就合并计算
else if(flag1) ret=lret;//只在左子树
else if(flag2) ret=rret;//只在右子树
return ret;
}
void Solve(){
int n,m;scanf("%d%d",&n,&m);
build(1,n,1);
for(int i=1;i<=m;i++){
int op;
scanf("%d",&op);
if(op==1){
int l,r;
scanf("%d%d",&l,&r);
if(l>r) swap(l,r);
Tree ans=query(l,r,1,n,1);
printf("%d\n",ans.sub);
}
else{
int p,s;
scanf("%d%d",&p,&s);
update(p,s,1,n,1);
}
}
}
int main(){
Solve();
return 0;
}
hzoi