首页 > 代码库 > D. Black Hills golden jewels 二分答案 + 二分判定

D. Black Hills golden jewels 二分答案 + 二分判定

http://codeforces.com/gym/101064/problem/D

 

题目是给定一个数组,如果两两组合,有C(n, 2)种结果,(找出第一个大于等于第k大的结果)

思路,

二分答案val,判断如下。

先把数组排序。

然后暴力枚举每个数a[i],那么找出第一个大于val - a[i]的,中间的数字和它组合。都是<=val的

统计这些数字的个数,如果大于等于k就是可行解。

 

hack。

二分答案的时候,明显下界是a[1] + a[2]。上界是a[n] + a[n - 1]

如果用begin = 1。end = 5e10L是错的

begin可以是0

 

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e5 + 20;
LL a[maxn];
map<LL, int>book;
LL n, k;
bool check(LL val) {
    LL total = 0;
    for (int i = 1; i <= n; ++i) {
        LL dis = val - a[i];
        if (val < 2 * a[i]) break;
        if (dis >= a[n]) {
            total += n - i;
        } else {
            int pos = upper_bound(a + 1, a + 1 + n, dis) - a;
            total += pos - 1 - i;
        }
        if (total >= k) return true;
    }
////    cout << total << endl;
//    if (total > k) return true;
    return false;
}
void work() {
    IOS;
    cin >> n >> k;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    sort(a + 1, a + 1 + n);
//    cout << check(7) << endl;
    LL be = a[1] + a[2];
    LL en = a[n] + a[n - 1];
    assert(be <= en);
//    cout << check(0) << endl;
    while (be <= en) {
        LL mid = (be + en) >> 1;
        if (check(mid)) {
            en = mid - 1;
        } else be = mid + 1;
    }
//    assert(be <= a[n] + a[n - 1]);
    cout << be << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}

 

D. Black Hills golden jewels 二分答案 + 二分判定