zoj 3278 & scau_oj 10273 8G Island (二分)

来源:互联网 发布:java launcher.dll 编辑:程序博客网 时间:2024/05/22 07:00

题意:

两个数组,元素个数分别为n和m。两两相乘可得n*m个数,求第k大的数。


思路:

本渣是听了别人二分的想法后才写出的。

两数组皆 非升序 排序。


首先,二分枚举第k大的数可能是多少。

假设当前枚举到mid,则计算大于等于mid的数有多少个。设之为tmp个。

若tmp > k,说明 第k大的数比mid大

若tmp < k,说明 第k大的数比mid小

若tmp = k, 分两种情况:

若n*m个数中存在等于mid的,则mid为第k大的数

否则,第k大的数比mid大 


其中,在找大于等于mid的数有多少个时,采用的是枚举第一个数组,二分第二个数组的方法。

同理,在找是否存在等于mid的数也是采用同样的方法。


#include <cstdio>#include <ctime>#include <cstdlib>#include <iostream>#include <cstring>#include <algorithm>using namespace std;typedef long long ll;#define debug(x) <<#x<<":"<<(x)const int maxn = 100010;ll n, m, k;ll boy[maxn], girl[maxn];bool cmp(const ll a, const ll b) {    return a > b;}ll countAt(ll x, int i) {    int l = 0;    int r = m - 1;    while(l <= r) {        int m = l + r;        m >>= 1;        if(boy[i] * girl[m] < x)            r = m - 1;        else            l = m + 1;    }    return l;}ll count(ll x) {    ll result = 0;    for(int i = 0; i < n; i++)        result += countAt(x, i);    return result;}bool findAt(ll x, int i){    int l = 0;    int r = m - 1;    while(l <= r){        int m = l + r;        m >>= 1;        ll tmp = girl[m] * boy[i];        if(tmp == x)            return 1;        else if(tmp < x)            r = m - 1;        else            l = m + 1;    }    return 0;}bool find(ll x){    for(int i = 0; i < n; i++)        if(findAt(x, i))            return 1;    return 0;}ll solve() {    ll result = 0;    ll min = boy[n - 1] * girl[m - 1];    ll max = boy[0] * girl[0];    while(min <= max) {        ll mid = min + max;        mid >>= 1;        ll tmp = count(mid);//        cout debug(min)<<" " debug(max)<<" " debug(mid)<<" " debug(tmp)<<endl;        if(tmp == k) {            if(find(mid)) {                result = mid;                break;            } else                min = mid + 1;        } else if(tmp < k)            max = mid - 1;        else            min = mid + 1, result = mid;    }    return result;}int main() {    while(cin>>n >>m >>k) {        for(int i = 0; i < n; i++)            cin>>boy[i];        for(int i = 0; i < m; i++)            cin>>girl[i];        sort(boy, boy + n, cmp);        sort(girl, girl + m, cmp);//        for(int i = 0; i < n; i++)//            printf("%d ", boy[i]);//            puts("");//        for(int i = 0; i < m; i++)//            printf("%d ", girl[i]);//            puts("");        cout<<solve()<<endl;    }    return 0;}


0 0
原创粉丝点击