zoukankan      html  css  js  c++  java
  • zoj 3278 8G Island(二分)

    题意:给出n个元素的数组a和m个元素的数组b,求数组a中元素与数组b中元素相乘所得乘积的第k大值;

    思路:暴力超时,采用二分;先将两数组从大到小排序,外层二分枚举答案,内层二分查找与当前枚举值相等的乘积所在的区间;

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    typedef long long ll;
    #define inf 100000000010
    using namespace std;
    ll kth,n,m;
    ll a[500010],b[500010];
    int cmp(int a1,int b1)
    {
        return a1>b1;
    }
    int main()
    {
        int k,i,j;
        while(scanf("%lld%lld%lld",&n,&m,&kth)!=EOF)
        {
            memset(a,0,sizeof(a));
            memset(b,0,sizeof(b));
            for(i=1;i<=n;i++) scanf("%lld",&a[i]);
            for(i=1;i<=m;i++) scanf("%lld",&b[i]);
            sort(a+1,a+n+1,cmp);
            sort(b+1,b+m+1,cmp);
            b[0]=inf;b[m+1]=-1;
            ll Min=a[n]*b[m];
            ll Max=a[1]*b[1];
            ll Low=Min;
            ll High=Max;
            ll ans=Max;
            while(Low<=High)
            {
                ll Mid=(Low+High)/2;
                ll key=Mid;
                ll s1=0,s2=0;
                for(i=1;i<=n;i++)
                {
                    int low,high,res;
                    ll val=a[i]*b[1];
                    ll val2=a[i]*b[m];
                    if(val2>key)
                    {
                        s1+=m;
                        continue;
                    }
                    if(val<key)
                    {
                        s2+=m;
                        continue;
                    }
                    low=1,high=m,res=0;
                    while(low<=high)
                    {
                        int mid=(low+high)/2;
                        val=a[i]*b[mid];
                        val2=a[i]*b[mid+1];
                        if(val>key&&val2<=key)
                        {
                            res=mid;
                            break;
                        }
                        else if(val2>key)
                            low=mid+1;
                        else
                            high=mid-1;
                    }
                    s1+=res;
                    low=1,high=m,res=m+1;
                    while(low<=high)
                    {
                        int mid=(low+high)/2;
                        val=a[i]*b[mid];
                        val2=a[i]*b[mid-1];
                        if(val<key&&val2>=key)
                        {
                            res=mid;break;
                        }
                        else if(val2<key)
                        {
                            high=mid-1;
                        }
                        else
                            low=mid+1;
                    }
                    s2+=(m-res+1);
                }
                ll left=s1+1;
                ll right=n*m-s2;
                if(left<=kth&&kth<=right)
                {
                    ans=key;break;
                }
                else if(kth<left)
                {
                    Low=Mid+1;
                }
                else High=Mid-1;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    [NOI2010] 能量采集 (数学)
    mysql双主操作记录
    linux查看版本
    netty
    idea修改文件,target目录对应的文件消失
    oracle11g的分区(range、list)索引测试
    There is a cycle in the hierarchy解决办法
    git学习转廖雪峰
    解决SVN Cleanup错误: Failed to run the WC DB work queue associated with
    nginx之 proxy_pass
  • 原文地址:https://www.cnblogs.com/dashuzhilin/p/4574906.html
Copyright © 2011-2022 走看看