4875 第k大数(二分)

题目描述
有两个序列a,b,它们的长度分别为n和m,那么将两个序列中的元素对应相乘后得到的n*m个元素从大到小排列后的第k个元素是什么?

输入
输入的第一行为一个正整数T (T<=10),代表一共有T组测试数据。

每组测试数据的第一行有三个正整数n,m和k(1<=n, m<=100000,1<=k<=n*m),分别代表a序列的长度,b序列的长度,以及所求元素的下标。第二行为n个正整数代表序列a。第三行为m个正整数代表序列b。序列中所有元素的大小满足[1,100000]。

输出
对于每组测试数据,输出一行包含一个整数代表第k大的元素是多少。

样例输入 Copy
3
3 2 3
1 2 3
1 2
2 2 1
1 1
1 1
2 2 4
1 1
1 1
样例输出 Copy
3
1
1

#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<map>
#include<bits/stdc++.h>
#include<stack>
#include<functional>
#include<cstring>
#include<set>
#include<strstream>
#include<vector>
#define mod 1000000007
#define mst(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=100000+8;
ll a[maxn];
//int dp[maxn][maxn];
//int s[maxn][maxn];
int f[maxn];
ll b[maxn];
int v[maxn]={0,12,8,9,5};
int w[maxn]={0,15,10,12,8};
int x[maxn];
int n,m;
ll k;
vector<int>vec;

ll cmp(ll a, ll b)
{
    return a>b;
}


ll judge(ll x)//统计>=x的数量
{
    ll sum=0,j=m-1;
    for(int i=0;i<n;i++)
    {
        while(j&&a[i]*b[j]<x)j--;
        if(a[i]*b[j]>=x)sum+=j+1;
    }
    return sum;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll res=0;
        scanf("%d%d%lld",&n,&m,&k);
        for(int i=0;i<n;i++)
        {
            scanf("%lld", &a[i]);
        }
        for(int j=0;j<m;j++)
        {
            scanf("%lld", &b[j]);
        }
        sort(a,a+n,cmp);
        sort(b,b+m,cmp);
        ll lf=a[n-1]*b[m-1];
        ll rt=a[0]*b[0];
        while(lf<=rt)
        {
            ll mid=(lf+rt)/2;
            if(judge(mid)>=k)
            {
                res=mid;
                lf=mid+1;
            }
            else
            {
                rt=mid-1;
            }
        }
        cout<<res<<endl;
        //cout<<lf<<endl;

    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一百个Chocolate

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值