BZOJ4476 送礼物
这道题真是有趣呀。
其实就是一个分数规划问题,用一个二分加log来得去掉分母。
分四种情况讨论
1.lenth > L && num ( max ) > num ( min )
2.lenth > L && num ( max ) < num ( min )
3.lenth == L && num ( max ) > num ( min )
4.lenth == L && num ( max ) < num ( min )
1,2种情况中最大值与最小值一定在选择序列两端,设左右端点编号为i,j
1. ( Vi - Vj ) / ( i - j + k ) = ans -> ( Vi - i * ans ) - ( Vj - j * ans ) = k * ans
二分ans并check左式最大值是否大于右式
2.( Vj - Vi ) / ( i - j + k ) = ans -> ( Vj + j * ans ) - ( Vi + i * ans ) = k * ans
同情况1
3,4用单调队列for一遍就可以了
1 #include<cstdio> 2 #include<algorithm> 3 #include<cassert> 4 //#define DEBUG 5 using namespace std ; 6 7 const int MAXN = 5 * 100000 + 20 ; 8 int N , K , L , R ; 9 long long a [ MAXN ] ; 10 int p [ MAXN ] ; 11 12 template < class T1 , class T2 > 13 void max_equal ( T1 & a , const T2 & b ) { 14 if ( a < b ) a = b ; 15 } 16 17 double solve1 ( const double M ) { 18 #define f(i) (a[i]-M*(i)) 19 double ans = -1e9 ; 20 int l = 0 , r = -1 ; 21 for ( int i = L ; i <= N ; ++ i ) { 22 while ( r - l + 1 >= 1 && i - p [ l ] + 1 > R ) ++ l ; 23 while ( r - l + 1 >= 1 && ! ( f ( p [ r ] ) < f ( i - L + 1 ) ) ) -- r ; 24 p [ ++ r ] = i - L + 1 ; 25 max_equal ( ans , f ( i ) - f ( p [ l ] ) ) ; 26 } 27 return ans ; 28 #undef f 29 } 30 31 double Solve1 () { 32 double L = 0 , R = 1e4 ; 33 while ( R - L >= 1e-10 ) { 34 const double M = ( L + R ) / 2 ; 35 if ( solve1 ( M ) >= K * M ) L = M ; 36 else R = M ; 37 } 38 return ( L + R ) / 2 ; 39 } 40 41 double solve2 ( const double M ) { 42 #define f(i) (a[i]+M*(i)) 43 double ans = -1e9 ; 44 int l = 0 , r = -1 ; 45 for ( int i = L ; i <= N ; ++ i ) { 46 while ( r - l + 1 >= 1 && i - p [ l ] + 1 > R ) ++ l ; 47 while ( r - l + 1 >= 1 && ! ( f ( p [ r ] ) > f ( i - L + 1 ) ) ) -- r ; 48 p [ ++ r ] = i - L + 1 ; 49 max_equal ( ans , f ( p [ l ] ) - f ( i ) ) ; 50 } 51 return ans ; 52 #undef f 53 } 54 55 double Solve2 () { 56 double L = 0 , R = 1e4 ; 57 while ( R - L >= 1e-10 ) { 58 const double M = ( L + R ) / 2 ; 59 if ( solve2 ( M ) >= K * M ) L = M ; 60 else R = M ; 61 } 62 return ( L + R ) / 2 ; 63 } 64 65 double Solve3 () { 66 double ans = -1e9; 67 int l = 0 , r = -1 ; 68 for ( int i = 1 ; i <= N ; ++ i ) { 69 while ( r - l + 1 >= 1 && i - p [ l ] + 1 > L ) ++ l ; 70 while ( r - l + 1 >= 1 && ! ( a [ p [ r ] ] < a [ i ] ) ) -- r ; 71 p [ ++ r ] = i ; 72 max_equal ( ans , a [ i ] - a [ p [ l ] ] ) ; 73 } 74 return ans / ( L - 1 + K ) ; 75 } 76 77 double Solve4 () { 78 double ans = -1e9; 79 int l = 0 , r = -1 ; 80 for ( int i = 1 ; i <= N ; ++ i ) { 81 while ( r - l + 1 >= 1 && i - p [ l ] + 1 > L ) ++ l ; 82 while ( r - l + 1 >= 1 && ! ( a [ p [ r ] ] > a [ i ] ) ) -- r ; 83 p [ ++ r ] = i ; 84 max_equal ( ans , a [ p [ l ] ] - a [ i ] ) ; 85 } 86 return ans / ( L - 1 + K ) ; 87 } 88 89 double solve () { 90 scanf ( "%d%d%d%d" , & N , & K , & L , & R ) ; 91 for ( int i = 1 ; i <= N ; ++ i ) scanf ( "%lld" , & a [ i ] ) ; 92 return max ( max ( Solve1 () , Solve2 () ) , max ( Solve3 () , Solve4 () ) ) ; 93 } 94 95 int main () { 96 int T ; 97 scanf ( "%d" , & T ) ; 98 while ( T -- ) printf ( "%.4lf\n" , solve () ) ; 99 return 0 ; 100 }