采用双二分,先对两个数组按降序排列,两两相乘的值在a[0]*b[0] 和a[n-1]*b[n-1]之间,n为数组长度
mid_mul=(a[0]*b[0] +a[n-1]*b[n-1])/2, 这样我们只要验证a[i]*b[j] >= mid_mul 的个数为n个就行。这里的时间复杂度是O(log(max) ) , max=a[0]*b[0]
验证部分是固定数组a,对b二分,统计a[i]*b[j] >= mid_mul 的个数。这里的时间复杂度是O(n*log(n))
总的时间复杂度是 O(n*log(n)*log(max) ) ,max=a[0]*b[0]。 当n很大的时候小于 O(n^2)
代码:
#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
int a[1024], b[1024], n, c[1024], index = 0;
int calc(int x, int v)
{
if (x * b[0] < v)
return 0;
int l = 0, r = n - 1, mid;
while (l < r)
{
mid = ((l + r) >> 1) + 1;
if (x * b[mid] >= v)
l = mid;
else
r = mid - 1;
}
return l + 1;
}
void calc2(int x, int v, int& tot)
{
if (x * b[0] < v)
return;
int l = 0, r = n - 1, mid;
while (l < r)
{
mid = ((l + r) >> 1) + 1;
if (x * b[mid] > v)
l = mid;
else
r = mid - 1;
}
for (r = 0; r <= l; r++)
{
//printf("%d\n", x * b[r]);
c[index] = x * b[r];
index ++;
}
tot += l + 1;
}
int main()
{
int i, j, l, r, mid, num;
scanf("%d", &n);//数组长度
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
for (i = 0; i < n; i++)
{
scanf("%d", &b[i]);
}
sort(b, b + n, greater<int>());
sort(a, a + n, greater<int>());
l = a[n - 1] * b[n - 1];
r = a[0] * b[0];
while (l < r)
{
mid = ((l + r) >> 1) + 1;
num = 0;
for (j = 0; j < n; j++)
{
num += calc(a[j], mid);
}
if (num >= n)
l = mid;
else
r = mid - 1;
}
int tot = 0;
for (i = 0; i < n; i++)
{
calc2(a[i], l, tot);
}
sort(c, c + index, greater<int>());
for(i = 0; i < index; i++)
{
printf("%d\n", c[i]);
}
for (; tot < n; tot++)
{
printf("%d\n", l);
}
return 0;
}
|