poj 2750 Potted Flower (线段树)

http://poj.org/problem?id=2750

/*
问题描述:给定一个环形序列,进行在线操作,每次修改一个元素,输出环上的最大连续子列的和,但不能是完全序列。
算法:把环从一个地方,切断拉成一条直线,用线段树记录当前区间的非空最大子列和当前区间的非空最小子列。
动态规划解决过静态的序列最大连续子序列和问题,时间复杂度可以达到 n(环形序列可能复杂度更高)。但是这里涉及到动态更新,更新频度很大,如果计算子序列和复杂度仍然是n,就会非常耗时。
如果环上的数都是正整数,答案是:环上数的总和-根结点的非空最小子列;否则,答案是:max{根结点的非空最大子列, 环上数的总和-根结点的非空最小子列}


一开始想到,如果将环从一点断开,那么最大和如果包括断点的最后一个点和第一个点,那该如何求
,仔细看了一下 ,终于向明白了,如果 段的最大自序列包括 断点 那么断点一定是正数;
  那么   环上数的总和-根结点的非空最小子列,就将断点包括了。



*/

#include<stdio.h>
#include<iostream>
#define N 100050
using namespace std;
int n,m;
int a[N];
struct node
{
    int l,r,sum;
    int xmax,xmin;
    int lmax,lmin;
    int rmax,rmin;
}p[N*3];
void update(int x)
{
    p[x].sum=p[x*2].sum+p[x*2+1].sum;

       p[x].lmax=max(p[x*2].lmax,p[x*2].sum+p[x*2+1].lmax);
       p[x].rmax=max(p[x*2+1].rmax,p[x*2].rmax+p[x*2+1].sum);//跨区间求最值
       p[x].xmax=max(max(p[x*2].xmax,p[x*2+1].xmax),p[x*2].rmax+p[x*2+1].lmax);

     p[x].lmin=min(p[x*2].lmin,p[x*2].sum+p[x*2+1].lmin);
     p[x].rmin=min(p[x*2+1].rmin,p[x*2].rmin+p[x*2+1].sum);
     p[x].xmin=min(min(p[x*2].xmin,p[x*2+1].xmin),p[x*2].rmin+p[x*2+1].lmin);


}
void build(int x,int l,int r)
{
    p[x].l=l;
    p[x].r=r;
    if(l==r)
    {
        p[x].sum=p[x].xmax=p[x].xmin=a[l];
        p[x].lmax=p[x].lmin=a[l];
        p[x].rmax=p[x].rmin=a[l];
        return ;
    }
    int mid=(l+r)/2;
    build(x*2,l,mid);
    build(x*2+1,mid+1,r);

    update(x);

}
void change(int x,int pos,int y)
{

    if(p[x].l==p[x].r&&p[x].l==pos)
    {
        p[x].sum=p[x].xmax=p[x].xmin=y;
        p[x].lmax=p[x].lmin=y;
        p[x].rmax=p[x].rmin=y;
        return ;
    }

    int mid=(p[x].l+p[x].r)/2;
    if(pos<=mid)change(x*2,pos,y);
    else  change(x*2+1,pos,y);

    update(x);

}
int main()
{
    scanf("%d",&n);

        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        int pos,y;
        while(m--)
        {
            scanf("%d%d",&pos,&y);
            change(1,pos,y);
            //printf("%d %d %d\n",p[1].sum,p[1].xmax,p[1].xmin);
            if(p[1].sum==p[1].xmax)
            {
                printf("%d\n",p[1].sum-p[1].xmin);
            }
            else
            {
                printf("%d\n",max(p[1].xmax,p[1].sum-p[1].xmin));
            }
        }


}

  

posted @ 2012-04-19 21:40  Szz  阅读(433)  评论(0)    收藏  举报