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));

            }

        }





}

  

你可能感兴趣的:(poj)