思路:由于N<=10000 ,所以我们不可能吧集合C中的元素全部算出来O(n^2),显然不行,这样的话,你还没求出集合C就已经TLE,根本没时间求第k大的值。
所以我们要换种角度,题目要求我们求集合c中第k大的数(用num_k表示),我们只要找出集合C中<=num_k的元素个数为m=n^2-k+1个即可。
这样我们先对A集合与B集合元素进行排序,先锁定集合C中元素的范围,在这个范围里面进行二分,再在这个二分里嵌套二分求<=当前num_k的元素的个数less_num。无限的去逼近num_k。
/*
* hrbeu1211.c
*
* Created on: 2011-9-19
* Author: bjfuwangzhu
*/
#include<stdio.h>
#include<stdlib.h>
#define nmax 10001
int numa[nmax], numb[nmax], n, k;
int cmp(const void *a, const void *b) {
return *(int *) a - *(int *) b;
}
int bbsearch(int key, int m) {
int i, left, right, mid, mm;
for (i = 0, mm = 0; i < n; i++) {
left = 0, right = n - 1;
while (left <= right) {
mid = (left + right) >> 1;
if (numa[i] * numb[mid] > key) {
right = mid - 1;
} else {
left = mid + 1;
}
}
mm += left;
if (mm > m) {
break;
}
}
return mm;
}
void solve() {
int left, right, mid, mm, m;
m = n * n - k + 1;
left = numa[0] * numb[0], right = numa[n - 1] * numb[n - 1];
while (left <= right) {
mid = (left + right) >> 1;
mm = bbsearch(mid, m);
if (mm >= m) {
right = mid - 1;
} else {
left = mid + 1;
}
}
printf("%d\n", left);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int t, i;
while (~scanf("%d", &t)) {
while (t--) {
scanf("%d %d", &n, &k);
for (i = 0; i < n; i++) {
scanf("%d", numa + i);
}
for (i = 0; i < n; i++) {
scanf("%d", numb + i);
}
qsort(numa, n, sizeof(numa[0]), cmp);
qsort(numb, n, sizeof(numb[0]), cmp);
solve();
}
}
return 0;
}