[Vijos 1083] 小白逛公园 · 线段树

来源:互联网 发布:三菱plc编程图形图 编辑:程序博客网 时间:2024/05/02 02:26

总体为带单点修改的查询区间最大连续子段和。

对每个区间维护四个值: 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_JUDGEfreopen("1083.in" , "r" , stdin) ;freopen("1083.out" , "w" , stdout) ;#endifn = 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 ;}
其实我也不知道怎么会TLE  明明随机数据只跑了400ms orz

0 0