查找v
/*
* 在[l, h)范围内查找值v,返回下标
* 假设a数组已经按从小到大排序
* 失败返回-1
*/
int bs(int a[], int l, int h, int v)
{
int m;
while (l < h)
{
m = (l + h) >> 1;
if (a[m] == v)
{
return m;
}
if (a[m] < v)
{
l = m + 1;
}
else
{
h = m;
}
}
return -1;
}
查找大于等于v的第一个值
/*
* 传入参数必须在a[l]与a[h]之间
* 假设a数组已经按从小到大排序
* 返回值l总是合理的
*/
int bs(int a[], int l, int h, int v)
{
int m;
while (l < h)
{
m = (l + h) >> 1;
if (a[m] < v)
{
l = m + 1;
}
else
{
h = m;
}
}
return l;
}
查找小于等于v的最后一个值
/*
* 在下标[l, r]范围内查找,返回下标
* 假设a数组已经按从小到大排序
* 失败返回-1
*/
int bs(int a[], int l, int r, int v)
{
int m;
while (l < r)
{
m = (l + r + 1) >> 1;
if (a[m] > v)
{
r = m - 1;
}
else
{
l = m;
}
}
if (a[l] > v)
{
return -1;
}
return l;
}
二分套二分
/*
* 二分套二分
* 数组A同数组B组合乘积,二分查找第K大
*/
typedef long long ll;
const int MAXN = 5e4 + 10;
ll N, K;
ll A[MAXN];
ll B[MAXN];
// 查找小于x的元素个数
ll check(ll x)
{
ll j = N, ans = 0;
for (int i = 1; i <= N; i++)
{
for (; j > 0;)
{
if (A[i] * B[j] > x)
{
j--;
}
else
{
break;
}
}
ans += j;
}
return ans;
}
int main(int argc, const char * argv[])
{
cin >> N >> K;
for (int i = 1; i <= N; i++)
{
scanf("%lld %lld", A + i, B + i);
}
sort(A + 1, A + N + 1);
sort(B + 1, B + N + 1);
ll ans = 0;
ll key = N * N - K + 1;
ll low = A[1] * B[1]; // 初始最小值
ll high = A[N] * B[N]; // 初始最大值
while (high - low > 1)
{
ll mid = (low + high) >> 1;
if (check(mid) >= key)
{
ans = mid;
high = mid;
}
else
{
low = mid;
}
}
cout << ans << '\n';
return 0;
}
修改 二分套二分 初始最大值赋值 2018.5.8