51nod 1105 第K大的数

27 篇文章 0 订阅

题意就不说了。。我真是菜哭了,四级都不能随手切,,感觉NOIP药丸。。。
一眼二分,但是怎么判断一直没有想到、、后来看了别人的题解才知道tmd原来是log方的,亏我一直在想log的,,,其实看看数据范围就知道是可以log方。。。判断就是直接判断,,,先把a和b排序,然后确定当前二分的数所在的范围(即是由a中的哪个数组成的),然后再二分b中匹配的位置,然后每次用n减去,就是小于当前二分数的数字的数量。。。然后就能直接二分判断了,,我真是傻。。

uses math;
var
        i,j:longint;
        p,n,m,k,ans,l,r,mid:int64;
        a,b:array[0..100000]of int64;
procedure qsort(l,r:longint);
var
        i,j:longint;
        t,m:int64;
begin
        i:=l;
        j:=r;
        m:=a[(l+r)div 2];
        repeat
                while a[i]<m do inc(i);
                while a[j]>m do dec(j);
                if i<=j then
                begin
                        t:=a[i];
                        a[i]:=a[j];
                        a[j]:=t;
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qsort(l,j);
        if i<r then qsort(i,r);
end;
procedure qsort1(l,r:longint);
var
        i,j:longint;
        t,m:int64;
begin
        i:=l;
        j:=r;
        m:=b[(l+r)div 2];
        repeat
                while b[i]<m do inc(i);
                while b[j]>m do dec(j);
                if i<=j then
                begin
                        t:=b[i];
                        b[i]:=b[j];
                        b[j]:=t;
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qsort1(l,j);
        if i<r then qsort1(i,r);
end;
function search(y,x:int64):int64;
var
        i,j:longint;
        ans,l,r,mid:int64;
begin
        l:=1;
        r:=n;
        ans:=n;
        while l<=r do
        begin
                mid:=(l+r)div 2;
                if a[y]*b[mid]>=x then
                begin
                        ans:=min(ans,mid);
                        r:=mid-1;
                end
                else begin
                        l:=mid+1;
                end;
        end;
        exit(ans);
end;
function check(x:int64):boolean;
var
        i,j,ans:longint;
begin
        ans:=0;
        for i:=1 to n do
        begin
                if a[i]*b[n]<x then continue;
                ans:=ans+n-search(i,x)+1;
        end;
        if ans>=m then exit(true)
        else exit(false);
end;
begin
        readln(n,m);
        for i:=1 to n do read(a[i],b[i]);
        qsort(1,n);
        qsort1(1,n);
        l:=a[1]*b[1];
        r:=a[n]*b[n];
        while l<=r do
        begin
                mid:=(l+r)div 2;
                if check(mid)then
                begin
                        l:=mid+1;
                        ans:=mid;
                end
                else begin
                        r:=mid-1;
                end;
        end;
        writeln(ans);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值