您的位置:首页 > 产品设计 > UI/UE

cuit校赛--sort 第K个数

2017-05-30 13:56 155 查看
传送门


sort

发布时间: 2017年5月28日 21:29   最后更新: 2017年5月28日 21:33   时间限制: 1000ms   内存限制: 128M

描述

给两个序列A=(a1,a2,a3,…an)和B=(b1,b2,b3,…bm),A中有n个数,B中有m个数,把A中的每个数分别和B中的每个数乘起来得到n*m个数从小到大排序,求其中的第k个数。

输入

第一行包含三个整数:n(1<=n<=10000),m(1<=m<=10000),k(1<=k<=m*n)。

第二行有n个整数,表示序列A。

第三行有m个整数,表示序列B。

A和B中所有数都在[0,10000]。

每个测试样例后都有一个空格。

输出

对于每组测试数据,每行输出答案。

样例输入1 复制
1 3 3
1
3 2 1


样例输出1
3


样例输入2 复制
3 3 7
1 2 3
3 2 1


样例输出2
6


查看隐藏信息

先排序,最大的肯定是a[m-1]*b[n-1],二分就是在l=0,r=a[m-1]*b[n-1] 里找
按照顺序来找。

a 0 1 2 3 4 5 `````

b 0 1 2 3 4 5 `````

如果是没有重复数字的情况下。

那么第K大的数一定是 m*x+y

比如K是 11 a有6个数

那么 b的第一个数乘以a的6个数 已经到了第6位。

b的第二个数乘a的5个数就到了11位。

所以二分找第k大的数

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 10005;
#define ll long long
int a[maxn];
int b[maxn];
int m, n, k;
int getsum(int x)
{
int l = 0, r = n - 1;
while (l <= r)
{
int mid = (l + r) >> 1;
if (b[mid] <= x)
l = mid + 1;
else
r = mid - 1;
}
return l;
}
bool check(int x)
{
ll ans = 0;
for (int i = 0; i < m; i++)
{
if (!a[i])// 如果a[i] 是0的话 那么这一排m必取
{
ans += n;
continue;
}
int cnt = x / a[i];//a[i]* cnt=x; 求最大的cnt 其他比
//cnt小的 都要加起来
ans += getsum(cnt);//在b里找 比cnt小的
}
return ans >= k;
}
int main()
{
scanf("%d %d %d",&m,&n,&k);
for(int i=0;i<m;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++) scanf("%d",&b[i]);
sort(a,a+m);
sort(b,b+n);
int l = 0;
int r = a[m-1]*b[n-1];
while(l<=r)
{
int mid = (l+r)>>1;
if(check(mid)) r = mid-1;
else l = mid+1;
}
cout << l << endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: