BZOJ-1911: [Apio2010]特别行动队(DP+斜率优化)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911

嗯。。。方程很好想吧?f( i ) = max{ f( j - 1 ) + value( j , i ) } value( j , i ) 表示从i选取到j在连续一段中的价值。

然后化简:

令:

s[ i ] = x[ 1 ] + ... + s[ i ]

X( i ) = ( 2 * a * s[ i - 1 ] )

Y( i ) = ( a * s[ i - 1 ] * s[ i - 1 ] - b * s[ i - 1 ] + f[ i - 1 ] )

A( i ) = ( a * s[ i ] * s[ i ] + b * s[ i ] + c )

f( j - 1 ) + value( j , i )

= A( i ) + Y( j ) - s[ i ] * X( j )

然后令 j > k ,且 f( j - 1 ) + value( j , i ) > f( k - 1 ) + value( k , i ) ,则最终可化为:

( Y( j ) - Y( k ) ) / ( X( j ) - X( k ) ) < s[ i ] ,那么就是用单调队列维护凸单调性的斜率优化了,O( n )时间复杂度。

代码:

eaf81a4c510fd9f9f2054710272dd42a2834a4bc.jpg.png
#include 
#include 
#include 
 
using namespace std ;
 
#define MAXN 1000100
#define X( i ) ( 2 * a * s[ i - 1 ] )
#define Y( i ) ( a * s[ i - 1 ] * s[ i - 1 ] - b * s[ i - 1 ] + f[ i - 1 ] )
#define A( i ) ( a * s[ i ] * s[ i ] + b * s[ i ] + c )
#define value( j , i ) ( a * ( s[ i ] - s[ j - 1 ] ) * ( s[ i ] - s[ j - 1 ] ) + b * ( s[ i ] - s[ j - 1 ] ) + c + f[ j - 1 ] )
#define ll long long 
 
void getint( ll &t ) {
    int ch ; bool flag = false ;
    for ( ch = getchar(  ) ; ! ( ch >= '0' && ch <= '9' ) ; ch = getchar(  ) ) if ( ch == '-' ) flag = true ;
    t = ch - '0' ;
    for ( ch = getchar(  ) ; ch >= '0' && ch <= '9' ; ch = getchar(  ) ) t *= 10 , t += ch - '0' ;
    if ( flag ) t = - t ;
}
 
ll a , b , c , n , s[ MAXN ] , f[ MAXN ] ;
int Q[ MAXN ] , head , tail ;
 
double K( int i , int j ) {
    ll x = X( i ) - X( j ) , y = Y( i ) - Y( j ) ;
    double ret = double( y ) / double( x ) ;
    return ret ;
}
 
int main(  ) {
    getint( n ) ; getint( a ) , getint( b ) , getint( c ) ;
    s[ 0 ] = 0 ;
    for ( int i = 0 ; i ++ < n ; ) {
        ll x ; getint( x ) ; s[ i ] = s[ i - 1 ] + x ;
    }
    f[ 0 ] = 0 ; Q[ head = tail = 1 ] = 1 ;
    for ( int i = 0 ; i ++ < n ; ) {
        while ( head < tail && K( Q[ head ] , Q[ head + 1 ] ) < s[ i ] ) head ++ ;
        f[ i ] = value( Q[ head ] , i ) ;
        while ( head < tail && K( Q[ tail - 1 ] , Q[ tail ] ) > K( Q[ tail ] , i + 1 ) ) tail -- ;
        Q[ ++ tail ] = i + 1;
    }
    printf( "%lld\n" , f[ n ] ) ;
    return 0 ;
}

你可能感兴趣的:(BZOJ-1911: [Apio2010]特别行动队(DP+斜率优化))