zoukankan      html  css  js  c++  java
  • 51Nod1105 第K大的数

    Problem

    数组A和数组B,里面都有n个整数。

    数组C共有n^2个整数,分别是:

    A[0] * B[0],A[0] * B[1] ...... A[0] * B[n-1]

    A[1] * B[0],A[1] * B[1] ...... A[1] * B[n-1]

    ......

    A[n - 1] * B[0],A[n - 1] * B[1] ...... A[n - 1] * B[n - 1]

    是数组A同数组B的组合,求数组C中第K大的数。

    例如:

    A:1 2 3,B:2 3 4。

    A与B组合成的C为

         A[0]  A[1]  A[2]
    

    B[0] 2 3 4

    B[1] 4 6 8

    B[2] 6 9 12

    共9个数。

    Solution

    一种二分套二分,二分答案,check的时候对每个数二分找更小的,有一些细节需要处理。

    仔细考虑发现,找比二分的数小的数,只要扫一遍,另一个指针随时减。省掉一个log

    Code1

    #include<stdio.h>
    #include<set>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<string.h>
    #include<queue>
    #define mem(ss) memset(ss,0,sizeof(ss))
    #define rep(d, s, t) for(int d=s;d<=t;d++)
    #define rev(d, s, t) for(int d=s;d>=t;d--)
    typedef long long ll;
    typedef long double ld;
    typedef double db;
    #define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    using namespace std;
    const int MAXN=50020;
    ll n,k,a[MAXN],b[MAXN];
    ll cont(int cur,ll num){
        ll t=a[cur],ans=0;
        int l=1,r=n,mid;
        while(l<=r){
            mid=(l+r)/2;
            if(t*b[mid]<=num){
                l=mid+1;
                ans=mid;
            }
            else{
                r=mid-1;
            }
        }
        return ans;
    }
    bool check(ll x){
        ll ans=0;
        for(int i=1;i<=n;i++){
            ans+=cont(i,x);
        }
        return ans>=k;
    }
    int main() {
        io_opt;
        cin>>n>>k;
        k=n*n-k+1;
        for(int i=1;i<=n;i++){
            cin>>a[i]>>b[i];
        }
        sort(a+1,a+1+n);
        sort(b+1,b+1+n);
        ll l=a[1]*b[1],r=a[n]*b[n],mid,ans;
        while(l<=r){
            mid=(l+r)/2;
            if(check(mid)){
                r=mid-1;
                ans=mid;
            }
            else{
                l=mid+1;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

    Code2

    #include<stdio.h>
    #include<set>
    //#include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<string.h>
    #include<queue>
    #define mem(ss) memset(ss,0,sizeof(ss))
    #define rep(d, s, t) for(int d=s;d<=t;d++)
    #define rev(d, s, t) for(int d=s;d>=t;d--)
    typedef long long ll;
    typedef long double ld;
    typedef double db;
    #define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    //using namespace std;
    const int MAXN=50020;
    ll n,k,a[MAXN],b[MAXN];
    inline ll cont(int cur,ll num){
        ll t=a[cur],ans=0;
        int l=1,r=n,mid;
        while(l<=r){
            mid=(l+r)/2;
            if(t*b[mid]<=num){
                l=mid+1;
                ans=mid;
            }
            else{
                r=mid-1;
            }
        }
        return ans;
    }
    inline bool check(ll x){
        ll ans=0;
        int j=n;
        for(int i=1;i<=n;i++){
            while(a[i]*b[j]>x) j--;
            ans+=j;
        }
        return ans>=k;
    }
    int main() {
        //io_opt;
    
        scanf("%lld%lld",&n,&k);
        k=n*n-k+1;
        for(int i=1;i<=n;i++){
            scanf("%lld%lld",&a[i],&b[i]);
        }
        std::sort(a+1,a+1+n);
        std::sort(b+1,b+1+n);
        ll l=a[1]*b[1],r=a[n]*b[n],mid,ans=r;
        while(l<=r){
            mid=(l+r)/2;
            if(check(mid)){
                r=mid-1;
                ans=mid;
            }
            else{
                l=mid+1;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    从拟物化到扁平,再到Material Design
    如何写一个解释器(1):编译原理
    理解JavaScript中的原型继承(2)
    Redis简介
    谈谈积累
    Hadoop(三):MapReduce程序(python)
    Hadoop(二):MapReduce程序(Java)
    统计学习方法十:隐马尔科夫模型二
    统计学习方法十:隐马尔科夫模型
    统计学习方法九:EM算法
  • 原文地址:https://www.cnblogs.com/sz-wcc/p/11716505.html
Copyright © 2011-2022 走看看