pku2750 Potted Flower

问题描述:给定一个环形序列,进行在线操作,每次修改一个元素,输出上的最大连续子段的和。

分析:涉及到线段树的以下操作:维护区间左边开始的连续最大子段和,从右边开始的连续最大子段和,区间的最大子段和

 

#include <iostream>
using namespace std;

#define MAXN 100005
#define Min(a,b) (a<b?a:b)
#define Max(a,b) (a>b?a:b)

int n,m;

struct Node{
    
int l,r,mx,lmx,rmx,mn,lmn,rmn,sum,mnnum;
    
bool allpos;
}nod[
3*MAXN];


void buildtree(int u,int l,int r){
    nod[u].l
=l;
    nod[u].r
=r;
    nod[u].lmx
=INT_MIN;
    nod[u].rmx
=INT_MIN;
    nod[u].mx
=INT_MIN;
    nod[u].lmn
=INT_MAX;
    nod[u].rmn
=INT_MAX;
    nod[u].mn
=INT_MAX;
    nod[u].sum
=0;
    nod[u].mnnum
=INT_MAX;
    nod[u].allpos
=true;
    
if(r==l)
        
return;
    buildtree(
2*u,l,(l+r)/2);
    buildtree(
2*u+1,(l+r)/2+1,r);
}

void insert(int u,int l,int r,int val){
    
if(nod[u].l==&& nod[u].r==r){
        nod[u].mx
=val;
        nod[u].lmx
=val;
        nod[u].rmx
=val;
        nod[u].mn
=val;
        nod[u].lmn
=val;
        nod[u].rmn
=val;
        nod[u].sum
=val;
        nod[u].mnnum
=val;
        
if(val>=0)
            nod[u].allpos
=true;
        
else
            nod[u].allpos
=false;
        
return;
    }
    
if(l<=nod[2*u].r)
        insert(
2*u,l,r,val);
    
if(r>=nod[2*u+1].l)
        insert(
2*u+1,l,r,val);

    nod[u].allpos
=nod[2*u].allpos && nod[2*u+1].allpos;
    nod[u].sum
=nod[2*u].sum+nod[2*u+1].sum;


    nod[u].lmx
=Max(nod[2*u].lmx,nod[2*u].sum+nod[2*u+1].lmx);
    nod[u].rmx
=Max(nod[2*u+1].rmx,nod[2*u+1].sum+nod[2*u].rmx);


    
//nod[u].mx=Max(nod[2*u].rmx+nod[2*u+1].lmx,nod[2*u].mx,nod[2*u+1].mx);
    nod[u].mx=nod[2*u].rmx+nod[2*u+1].lmx;
    nod[u].mx
=Max(nod[u].mx,nod[2*u].mx);
    nod[u].mx
=Max(nod[u].mx,nod[2*u+1].mx);



    nod[u].lmn
=Min(nod[2*u].lmn,nod[2*u].sum+nod[2*u+1].lmn);
    nod[u].rmn
=Min(nod[2*u+1].rmn,nod[2*u+1].sum+nod[2*u].rmn);

    
//nod[u].mn=Min(nod[2*u].rmn+nod[2*u+1].lmn,nod[2*u].mn,nod[2*u+1].mn);
    nod[u].mn=nod[2*u].rmn+nod[2*u+1].lmn;
    nod[u].mn
=Min(nod[u].mn,nod[2*u].mn);
    nod[u].mn
=Min(nod[u].mn,nod[2*u+1].mn);


    nod[u].mnnum
=Min(nod[2*u].mnnum,nod[2*u+1].mnnum);
    
//环内最小的数,当环内元素全部为非负时用到
}

int main(){
    
int i,pos,a,mn;
    
while(scanf("%d",&n)!=EOF){
        buildtree(
1,1,n);
        mn
=INT_MAX;
        
for(i=1;i<=n;i++){
            scanf(
"%d",&a);
            
if(a<mn)
                mn
=a;
            insert(
1,i,i,a);
        }
        scanf(
"%d",&m);
        
for(i=0;i<m;i++){
            scanf(
"%d%d",&pos,&a);
            
if(a<mn)
                mn
=a;
            insert(
1,pos,pos,a);
            
if(nod[1].allpos)//当环内元素全为非负时
                printf("%d\n",nod[1].sum-nod[1].mnnum);
                
//解为环和去掉最小的一个元素
            else
                printf(
"%d\n",Max(nod[1].sum-nod[1].mn,nod[1].mx));
                
//解为环和减去最小子列和最大子列两者中的较大值
        }
    }
    
return 0;
}

posted @ 2008-11-12 19:23  Beetlebum  阅读(469)  评论(0编辑  收藏  举报