線段樹+DP 求區間連續最大子段和 hoj Candy

/* 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;
}

發佈了185 篇原創文章 · 獲贊 3 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章