线段树求最大子段和,由于是动态的且n,m均高达1e5,因此想到线段树
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=5000010;
ll num[N],add[N];
ll n,m;
ll max(ll aa,ll bb){ return aa>bb?aa:bb; }
struct TREE
{
ll lx,rx,l,r,sum,ans;
}tree[N];
void build(int k,int left,int right)
{
tree[k].l=left;
tree[k].r=right;//左右范围
if(left==right)
{
tree[k].sum=tree[k].lx=tree[k].rx=tree[k].ans=num[left];
return ;
}
int mid=(left+right)>>1;//二分拓展
build(k*2,left,mid);
build(k*2+1,mid+1,right);
tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
tree[k].lx=max(tree[k*2].lx,tree[k*2].sum+tree[k*2+1].lx);
tree[k].rx=max(tree[k*2+1].rx,tree[k*2+1].sum+tree[k*2].rx);
tree[k].ans=max(max(tree[k*2].ans,tree[k*2+1].ans),tree[k*2].rx+tree[k*2+1].lx);
}
TREE query(int k,int x,int y)
{
if(x<=tree[k].l&&tree[k].r<=y) return tree[k];
TREE a,b,res;
a.lx=a.rx=a.ans=a.ans=-1e9*2;
b.lx=b.rx=b.ans=b.ans=-1e9*2;
a.sum=b.sum=res.sum=0;
res.ans=-1e9*2;
ll mid=(tree[k].l+tree[k].r)>>1;
if(x<=mid)
{
a=query(k*2,x,y);
res.sum+=a.sum;
}
if(y>=mid+1)
{
b=query(k*2+1,x,y);
res.sum+=b.sum;
}
res.ans=max(a.rx+b.lx,max(a.ans,b.ans));
res.lx=max(a.lx,a.sum+b.lx);
res.rx=max(b.rx,b.sum+a.rx);
if(x>mid) res.lx=max(res.lx,b.lx);
if(y<mid) res.rx=max(res.rx,a.rx);
return res;
}
void change(ll k,ll x,ll y,ll ad,ll w)
{
if(ad<x||ad>y)return ;
else if(x==ad&&y==ad)
{
tree[k].lx=tree[k].rx=tree[k].sum=tree[k].ans=w;
return;
}
else
{
ll mid=(x+y)>>1;
change(k*2,x,mid,ad,w);
change(k*2+1,mid+1,y,ad,w);
tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
tree[k].lx=max(tree[k*2].lx,tree[k*2].sum+tree[k*2+1].lx);
tree[k].rx=max(tree[k*2+1].rx,tree[k*2+1].sum+tree[k*2].rx);
tree[k].ans=max(max(tree[k*2].ans,tree[k*2+1].ans),tree[k*2].rx+tree[k*2+1].lx);
return;
}
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>num[i];
build(1,1,n);
for(int i=1; i<=m; i++)
{
ll op,x,y;
cin>>op>>x>>y;
if(op==1)
{
if(x>y)swap(x,y);
TREE qwq=query(1,x,y);
cout<<qwq.ans<<endl;
}
else change(1,1,n,x,y);
}
return 0;
}