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

你可能感兴趣的:(pku)