LOJ#6384.「是男人就过8题——Pony.ai」SignLocation-决策单调性

说在前面

zjqqqaq给了一道题让me去写

题目

LOJ#6384传送门

下面是代码

me使用的是dp凸优化

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

int N , K ;
long long a[10005] , sa[10005] , sai[10005] ;
struct Data{
int ed , cnt ;
long long val ;
Data( int e = 0 , int c = 0 , long long v = 0 ):ed(e) , cnt(c) , val(v){} ;
bool operator < ( const Data &A ) const {
return val < A.val || ( val == A.val && cnt < A.cnt ) ;
}
} dp[10005] , que[10005] ;

int fr , ba ;

long long Val( int lf , int rg ){
long long rt = 0 ;
int len = rg - lf + 1 ;
if( len <= 2 ) return 0 ;
rt += ( sai[rg-1] - sai[lf+1] - ( sa[rg-1] - sa[lf+1] ) * ( lf + 1 ) ) * 2 ;
rt += ( sai[rg-2] - sai[lf] - ( sa[rg-2] - sa[lf] ) * ( rg - 1 ) ) * 2 ;
rt += ( sa[rg-1] - sa[lf] - a[lf] * ( len - 2 ) ) * lf ;
rt += ( a[rg] * ( len - 2 ) - ( sa[rg-1] - sa[lf] ) ) * ( N - rg + 1 ) ;
return rt ;
}
long long Val( Data &x , int now ){ return Val( x.ed , now ) + x.val ; }

int better( Data &x , Data &y ){
int lf = x.ed , rg = N , rt = N + 1 ;
while( lf <= rg ){
int mid = ( lf + rg ) >> 1 ;
long long t1 = Val( x , mid ) , t2 = Val( y , mid ) ;
if( t1 < t2 || ( t1 == t2 && x.cnt < y.cnt ) )
rt = mid , rg = mid - 1 ;
else lf = mid + 1 ;
} return rt ;
}

void Push( Data &x ){
while( ba > fr ){
int t1 = better( que[ba] , que[ba-1] ) , t2 = better( x , que[ba] ) ;
if( t1 > t2 || ( t1 == t2 && x.cnt < que[ba].cnt ) ) ba -- ;
else break ;
} que[++ba] = x ;
}

Data dp_check( long long delta ){
fr = 1 , que[ ba = 1 ] = Data( 0 , 0 , 0 ) ;
for( int i = 1 ; i <= N ; i ++ ){
while( ba > fr ){
long long v1 = Val( que[fr] , i ) , v2 = Val( que[fr+1] , i ) ;
if( v1 > v2 || ( v1 == v2 && que[fr].cnt > que[fr+1].cnt ) ) fr ++ ;
else break ;
} dp[i] = Data( i , que[fr].cnt + 1 , Val( que[fr] , i ) + delta ) ;
Push( dp[i] ) ;
}
Data res = Data( N , 1e9 , 1e18 ) ;
for( int i = 1 ; i <= N ; i ++ ){
dp[i].val += Val( dp[i].ed , N + 1 ) ;
if( dp[i] < res ) res = dp[i] ;
} return res ;
}

void solve(){
long long lf = 0 , rg = Val( 0 , N + 1 ) , ans ;
for( int t = a[N] / 2 , i = 1 ; i <= N ; i ++ )
if( a[i] <= t && a[i+1] > t ){
rg -= Val( 0 , i ) + Val( i , N + 1 ) ;
break ;
}

while( lf <= rg ){
long long mid = ( lf + rg ) >> 1 ;
Data res = dp_check( mid ) ;
if( res.cnt == K )
return ( void )printf( "%lld\n" , res.val - mid * K ) ;
if( res.cnt < K ) ans = res.val - mid * K , rg = mid - 1 ;
else lf = mid + 1 ;
} printf( "%lld\n" , ans ) ;
}

int main(){
while( scanf( "%d%d" , &N , &K ) != EOF ){
K = min( N , K ) ;
for( int i = 1 ; i <= N ; i ++ ){
scanf( "%lld" , &a[i] ) ;
sa[i] = sa[i-1] + a[i] ;
sai[i] = sai[i-1] + a[i] * i ;
} K ? solve() : (void)printf( "%lld\n" , Val( 0 , N + 1 ) ) ;
}
}


• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120