总体为带单点修改的查询区间最大连续子段和。
对每个区间维护四个值: left_max , right_max , sum , ans .分别是区间的最大前缀和,最大后缀和,区间总和,以及最大连续子段和(也就是要求的值)。
对于当前区间father[l,r] ,下属的两个区间分别为son1,son2,father的left_max等于 max (son1.left_max , son1.sum + son2.left_max),即左孩子的最大前缀和 或 左孩子的区间总和加上右孩子的最大前缀和(见下图)
对于最大后缀和也是一个意思,
那么father.ans 怎么合并呢:son1.right_max + son2.left_max 连起来构成了一个连续的子段,然后再和son1.ans、son2.ans比较取最大值。
代码的时候对于更新合并操作可以重载运算符来简化程序。
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int N = 500005;
int n,m,a[N],p,x,y;
struct arr {
int x,l,r,s;
}t[N * 4];
arr operator *( arr a , arr b ) {
arr c ;
c.s = a.s + b.s ;
c.x = max( max( a.x , b.x ) , a.r + b.l ) ;
c.l = max( a.l , a.s + b.l ) ;
c.r = max( b.r , b.s + a.r ) ;
return c ;
}
inline void build( int l , int r , int p ) {
if ( l == r ) {
t[ p ].s = t[ p ].l = t[ p ].r = t[ p ].x = a[ l ] ;
return ;
}
int mid = ( l + r ) >> 1 ;
build( l , mid , p + p + 1 ) ;
build( mid + 1 , r , p + p + 2 ) ;
t[ p ] = t[ p + p + 1 ] * t[ p + p + 2 ] ;
return ;
}
inline void edit( int l , int r , int p ) {
if ( l > r || l > x || r < x ) return ;
if ( l == r ) {
t[ p ].s = t[ p ].l = t[ p ].r = t[ p ].x = a[ l ] = y ;
return ;
}
int mid = ( l + r ) >> 1 ;
edit( l , mid , p + p + 1 ) ;
edit( mid + 1 , r , p + p + 2) ;
t[ p ] = t[ p + p + 1 ] * t[ p + p + 2 ] ;
return ;
}
inline arr query( int l , int r , int p ) {
if ( l > r || l > y || r < x ) return (arr){ -0x7fffff , -0x7fffff , -0x7fffff , -0x7fffff } ;
if ( x <= l && r <= y ) return t[ p ];
int mid = ( l + r ) >> 1;
arr ret,left,right;
left = query( l , mid , p + p + 1 ) ;
right = query( mid + 1, r , p + p + 2) ;
ret = left * right ;
return ret ;
}
int get() {
int p = 0 , t = 1 ; char x = getchar() ;
while ( x < '0' || x > '9') {
if ( x == '-' ) t = -t ;
x = getchar() ;
}
while ( x >= '0' && x <= '9' ) p = p * 10 + x - '0' , x = getchar() ;
return p * t ;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("1083.in" , "r" , stdin) ;
freopen("1083.out" , "w" , stdout) ;
#endif
n = get() ; m = get() ;
for (int i = 1 ; i <= n ; i++) a[ i ] = get() ;
build( 1 , n , 0 );
while ( m-- ) {
p = get() ; x = get() ; y = get() ;
if ( x > y ) swap( x , y ) ;
if ( p == 1 ) {
arr ans = query( 1 , n , 0 ) ;
printf("%d\n", ans.x) ;
}
else edit( 1 , n , 0 ) ;
}
return 0 ;
}