HOJ 2687 动态最大字段长

sl代表当前线段从最右端开始的最大长度,sr代表最左端

s代表当前线段和,ss当前最大字段长

ss的值从三种状态转移而来,ss[rt<<1],ss[rt<<1|1],sl[rt<<1]+sr[rt<<1|1];

即左儿子最大字段长,右儿子最大字段长,抑或由中间向两边延伸的最大字段长

用线段树维护上述变量

#include <stdio.h>
#include <iostream>
using namespace std;
const int maxn=100001;
int n,m;
int s[maxn<<2],sl[maxn<<2],sr[maxn<<2],ss[maxn<<2];
void pushup(int rt)
{
    s[rt]=s[rt<<1]+s[rt<<1|1];
    sl[rt]=max(s[rt<<1|1]+sl[rt<<1],sl[rt<<1|1]);
    sr[rt]=max(s[rt<<1]+sr[rt<<1|1],sr[rt<<1]);
    ss[rt]=max(ss[rt<<1],ss[rt<<1|1]);
    ss[rt]=max(ss[rt],sl[rt<<1]+sr[rt<<1|1]);
}
void init(int rt,int l,int r)
{
    int m=(l+r)>>1;
    if(l!=r)
    {
        init(rt<<1,l,m);
        init(rt<<1|1,m+1,r);
        pushup(rt);
    }
    else
    {
        scanf("%d",&s[rt]);
        sl[rt]=sr[rt]=ss[rt]=s[rt];
    }
}
void change(int rt,int l,int r,int t,int tt)
{
    if(l==t&&r==t)
    {
        sl[rt]=sr[rt]=ss[rt]=s[rt]=tt;
    }
    else
    {
        int m=(l+r)>>1;
        if(m>=t)
            change(rt<<1,l,m,t,tt);
        else
            change(rt<<1|1,m+1,r,t,tt);
        pushup(rt);
    }
}
int main()
{
    int t,tt;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init(1,1,n);
        while(m--)
        {
            scanf("%d%d",&t,&tt);
            change(1,1,n,t,tt);
            printf("%d
",ss[1]);
        }
    }
}
原文地址:https://www.cnblogs.com/acahesky/p/3243511.html