线段树+DP 求区间连续最大子段和 hoj Candy

来源:互联网 发布:淘宝的英树是正品吗 编辑:程序博客网 时间:2024/05/17 23:56
/* 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;}