[Gym - 101064D Black Hills golden jewels] 二分套二分
题目链接:[Gym - 101064D Black Hills golden jewels]
题意描述:给定N个数
a1,a2,…,an
,他们两两组成一个无序数对,求第K小的数对和。
(2≤N≤105,1≤K≤N∗(N−1)2,0≤ai≤109)
。
解题思路:
显然答案小于
2∗109
, 那么我们可以首先对数对和二分。求出小于等于这个数对和的个数有多少个。而对于每一个数对和,求小于它的个数, 我们首先枚举数对中较大的那个数,然后二分较小的那个数(可以等于)。总复杂度就是
log2(N∗log2N)
.
#include <bits/stdc++.h>
using namespace std;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
typedef __int64 LL;
const int MAXN = 1e5 + 5;
const LL INF = 0x3f3f3f3f3f3f3f3f;
LL A[MAXN];
LL N, K;
bool check (LL m) {
LL ks = 0;
for (int i = N - 1; i >= 1; i --) {
ks += lower_bound (A, A + i, m - A[i]) - A;
}
if (ks >= K) return true;
return false;
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
//FOUT;
#endif
while (~scanf ("%I64d %I64d", &N, &K) ) {
for (int i = 0; i < N; i ++) {
scanf ("%I64d", &A[i]);
}
sort (A, A + N);
LL lb = -1, ub = INF, mid;
while (lb <= ub) {
mid = (ub + lb) >> 1;
if (check (mid) ) {
ub = mid - 1;
} else {
lb = mid + 1;
}
}
printf ("%I64d\n", ub);
}
return 0;
}