Hrbeu 5012(二分逼近)

 

比较恶心的逼近 首先对2组数据排序

 

然后在形式上化作N*N的阵 使用DP变量保存查找深度

 

每次查询如果key值较小 左移一次 则排名增加(n-dp) 否则深度+1

 

使用二分逼近 返回ans 注意逼近时计算k的上下界

 

代码如下: 

 

 

#include  < iostream >
#include 
< algorithm >
using   namespace  std;

long  A[ 10010 ];
long  B[ 10010 ];
long  N,K;

bool  check( long  key)
{
    
long  i;
    
long  rank = 1 ;
    
long  dp = 0 ;

    
for  (i = N - 1 ;i >= 0 && dp <= N;)
    {
        
if  (key < A[i] * B[dp])
        {
            rank
+= (N - dp);
            
if  (rank > K)
            {
                
return   false ;
            }
            
-- i;
        }
        
else
        {
            
++ dp;
        }
    }

    
long  up = rank;

    rank
= 1 ;
    dp
= 0 ;
    
for  (i = N - 1 ;i >= 0 && dp <= N;)
    {
        
if  (key <= A[i] * B[dp])
        {
            rank
+= (N - dp);
            
if  (rank > K)
            {
                
return   false ;
            }
            
-- i;
        }
        
else
        {
            
++ dp;
        }
    }

    
long  down = rank;


    
return  rank >= up && rank <= down;
}

int  main()
{
    
long  T;
    scanf(
" %ld " , & T);

    
while  (T -- )
    {
        
long  i;

        scanf(
" %ld %ld " , & N, & K);

        
for  (i = 0 ;i < N; ++ i)
        {
            scanf(
" %ld " , & A[i]);
        }

        
for  (i = 0 ;i < N; ++ i)
        {
            scanf(
" %ld " , & B[i]);
        }

        sort(A,A
+ N);
        sort(B,B
+ N);


        
long  low = A[ 0 ] * B[ 0 ];
        
long  high = A[N - 1 ] * B[N - 1 ];

        
long  h = low,r = high,mid,ans = h;

        
while (h <= r)
        {
            mid
= (h + r) >> 1 ;
            
if ( ! check(mid))
            {
                ans
= mid;
                h
= mid + 1 ;
            }
            
else
            {
                r
= mid - 1 ;
            }
        }

        printf(
" %ld\n " ,ans);



    }
    
return   0 ;
}

你可能感兴趣的:(二分)