luogu -区间求最大和
线段树维护 最大前缀和,后缀和
小新经常陪小白去公园玩,也就是所谓的遛狗啦…
题目描述
在小新家附近有一条“公园路”,路的一边从南到北依次排着nnn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。
一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第aaa个和第bbb个公园之间(包括aaa、bbb两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。
那么,就请你来帮小白选择公园吧。
输入格式
第一行,两个整数NNN和MMM,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
接下来NNN行,每行一个整数,依次给出小白 开始时对公园的打分。
接下来MMM行,每行三个整数。第一个整数KKK,111或222。
K=1K=1K=1表示,小新要带小白出去玩,接下来的两个整数aaa和bbb给出了选择公园的范围(1≤a,b≤N1≤a,b≤N1≤a,b≤N)。测试数据可能会出现a>ba>ba>b的情况,需要进行交换;
K=2K=2K=2表示,小白改变了对某个公园的打分,接下来的两个整数ppp和sss,表示小白对第ppp个公园的打分变成了sss(1≤p≤N1≤p≤N1≤p≤N)。
其中,1≤N≤5000001≤N≤500 0001≤N≤500000,1≤M≤1000001≤M≤100 0001≤M≤100000,所有打分都是绝对值不超过100010001000的整数。
输出格式
小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。
输入输出样例
输入 #1
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3
输出 #1
2
-1
#include
using namespace std;
const int N=500010;
struct Tree
{
int pre,s,suf,v;
}tree[4*N];
int a[N];
Tree pushup(Tree &l,Tree &r )
{
Tree rt;
rt.pre=max(l.pre,l.v+r.pre);//最大前缀和
rt.suf=max(r.suf,r.v+l.suf);//最大后缀和
rt.v=l.v+r.v;//当前区间的和
rt.s=max(max(l.s,r.s),l.suf+r.pre);//最大子段和
return rt;
}
void build(int l,int r,int x)
{
if(l==r)
{
tree[x].pre=tree[x].suf=tree[x].s=tree[x].v=a[l];
return ;
}
int mid=(l+r)>>1;
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
tree[x]=pushup(tree[x<<1],tree[x<<1|1]);
}
void update(int pos,int c,int l,int r,int x)
{
if(l==r)
{
tree[x].pre=tree[x].suf=tree[x].s=tree[x].v=c;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) update(pos,c,l,mid,x<<1);
if(pos>mid) update(pos,c,mid+1,r,x<<1|1);
tree[x]=pushup(tree[x<<1],tree[x<<1|1]);
}
Tree query(int L,int R,int l,int r,int x)
{
if(L<=l&&R>=r)
{
return tree[x];
}
int mid=(l+r)>>1;
Tree ret,lret,rret;
int f1=0,f2=0;
if(L<=mid)
{
lret=query(L,R,l,mid,x<<1);
f1=1;
}
if(R>mid)
{
rret=query(L,R,mid+1,r,x<<1|1);
f2=1;
}
if(f1&&f2)
{
ret=pushup(lret,rret);
}else if(f1)
{
ret=lret;
} else if(f2)
{
ret=rret;
}
return ret;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
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.s);
}else
{
int p,s;
scanf("%d%d",&p,&s);
update(p,s,1,n,1);
}
}
}