/* f为从左端开始的最大子段和,b为从右端开始的最大子段和。
pushup中的为最大字段和的状态转移方程。*/
#include <stdio.h> #include <cstring> #define maxn 100001 #include <iostream> using namespace std; int m[maxn<<2],f[maxn<<2],b[maxn<<2],sum[maxn<<2]; void pushup(int rt) { m[rt]=max(m[rt<<1],m[rt<<1|1]); m[rt]=max(m[rt],b[rt<<1]+f[rt<<1|1]); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; f[rt]=max(f[rt<<1],sum[rt<<1]+f[rt<<1|1]); b[rt]=max(b[rt<<1|1],sum[rt<<1|1]+b[rt<<1]); } void build(int l,int r,int rt) { if(l==r) { scanf("%d",&m[rt]); f[rt]=b[rt]=sum[rt]=m[rt]; return ; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt); } void update(int c,int p,int l,int r,int rt) { if(l==r) { m[rt]=p; sum[rt]=f[rt]=b[rt]=p; return ; } int mid=(l+r)>>1; if(c<=mid) update(c,p,l,mid,rt<<1); else update(c,p,mid+1,r,rt<<1|1); pushup(rt); } int main() { int n,t,a,bb; while(scanf("%d%d",&n,&t)==2) { memset(m,0,sizeof(m)); memset(f,0,sizeof(f)); memset(b,0,sizeof(b)); memset(sum,0,sizeof(sum)); build(1,n,1); while(t--) { scanf("%d%d",&a,&bb); update(a,bb,1,n,1); printf("%d\n",m[1]); } } return 0; }
线段树+DP 求区间连续最大子段和 hoj Candy
最新推荐文章于 2022-04-25 15:28:00 发布