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 }

 

转载于:https://www.cnblogs.com/Christopher-Cao/p/5426451.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值