主要就是維護ls,rs,ms,s
通過dp(只有一點點)維護最大連續字段和
直接上代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=500005;
struct tr
{
int l,r,s,ls,rs,ms;
}tree[maxn*4];
int a[maxn],n,m;
void update(int now)
{
tree[now].s=tree[now<<1].s+tree[now<<1|1].s;
tree[now].ls=max(tree[now<<1].ls,tree[now<<1].s+tree[now<<1|1].ls);
tree[now].rs=max(tree[now<<1|1].rs,tree[now<<1|1].s+tree[now<<1].rs);
tree[now].ms=max(max(max(tree[now<<1].ls,tree[now<<1|1].rs),tree[now<<1].rs+tree[now<<1|1].ls),max(tree[now<<1].ms,tree[now<<1|1].ms));
}
void build(int l , int r , int now)
{
tree[now].l=l; tree[now].r=r;
if(l==r)
{
tree[now].s=a[l];
tree[now].ls=a[l];
tree[now].rs=a[l];
tree[now].ms=a[l];
}
else
{
int mid=(l+r)>>1;
build(l,mid,now<<1);
build(mid+1,r,now<<1|1);
update(now);
}
}
tr query(int l ,int r ,int now)
{
if(tree[now].l==l && tree[now].r==r)
return tree[now];
int mid=(tree[now].l+tree[now].r)>>1;
if(mid>=r)
return query(l,r,now<<1);
if(mid<l)
return query(l,r,now<<1|1);
tr ll=query(l,mid,now<<1);
tr rr=query(mid+1,r,now<<1|1);
tr yy;
yy.s=ll.s+rr.s;
yy.ls=max(ll.ls,ll.s+rr.ls);
yy.rs=max(rr.rs,rr.s+ll.rs);
yy.ms=max(max(max(ll.ls,rr.rs),ll.rs+rr.ls),max(ll.ms,rr.ms));
return yy;
}
void change(int l ,int r ,int k ,int x ,int now)
{
if(l==r && l==k)
{
tree[now].ls=tree[now].rs=tree[now].ms=tree[now].s=x;
return;
}
int mid=(l+r)>>1;
if(k<=mid)
{
change(l,mid,k,x,now<<1);
update(now);
}
else
{
change(mid+1,r,k,x,now<<1|1);
update(now);
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
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 q;
scanf("%d",&q);
if(q==1)
{
int a,b;
scanf("%d%d",&a,&b);
if(a>b)
printf("%d\n",query(b,a,1).ms);
else
printf("%d\n",query(a,b,1).ms);
}
else
{
int a,b;
scanf("%d%d",&a,&b);
change(1,n,a,b,1);
}
}
return 0;
}