51nod 1105---二分套二分

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1105


题意a序列和b序列,ab序列是 a和b两两组合,问你ab中第k大是多少。。


这题是个二分套二分,是个二分好题。。为什么好呢,因为这个二分容易写残疾啊。。。(总之就是我太弱了

接下来分析一下这个题的解法和要注意的地方。

一个显然的方法就是二分答案了,然后判断mid是第几大就可以了。。

但是,仔细一想?咦。。会不会二分的答案其实不是ab数组里面的呢?会不会ab里面有很多个一样的值我无法返回正确答案呢?


我们先分析二分时候我们计算的是什么。。

我们计算的mid在ab数组里面时候,枚举a,二分b就可以知道有几个大于等于mid了,


在设计二分的时候-当返回值大于等于k的时候,使得l=mid+1;(参考blog--《你真的会二分查找吗?》


我们这时候考虑一下我们会遇到的问题,

Q 计算的时候会不会有什么问题?例如mid不是ab数组里面的一个数。

A 我们先不考虑是不是ab数组里的一个数,我们计算的是比mid大的ab中的数有多少个。


Q     如果一个数是第k大但是这个数有很多呢?

A     (参考blog--《你真的会二分查找吗?》),这里返回第一个大于等于它的值。


会不会返回一个不在ab数组里的一个数呢?

A 答案是不会的,因为 这个问题可以划归到上一个问题,既然返回的是第一个大于等于它的值,那么如果mid不合法,那么一定存在一个和mid计算值一样的,并且这个合 法值要小于mid,(因为不存在的时候要向上取整的,自然虽然计算值一样但是存在的较小)。。


PS。。很多地方可能说的不对,望大家指正。


放代码:

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

const int maxn=50000;
long long n,k;
long long A[maxn],B[maxn];


long long Ca(long long x){
    long long f;
    long long ret1=0;
    for(int i=0;i<n;i++){
        f=x/A[i];
        if(x%A[i]!=0)
            f++;
        if(B[n-1]>=f)
            ret1+=(n-(long long)(lower_bound(B,B+n,f)-B));
    }
    return ret1;
}

int main()
{
    cin>>n>>k;
    for(int i=0;i<n;i++){
        cin>>A[i]>>B[i];
    }
    sort(A,A+n);
    sort(B,B+n);
    long long l=A[0]*B[0],r=A[n-1]*B[n-1],mid;
    while(l<=r){
        mid=(l+r)/2;
        long long x=Ca(mid);
        if(x>=k){
            l=mid+1;
        }
        else{
            r=mid-1;
        }
    }
    cout<<l-1<<endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值