Costume Party [Neal Wu, 2007]


It's Halloween! Farmer John is taking the cows to a costume party, but unfortunately he only has one costume. The costume fits precisely two cows with a length of S (1 <= S <= 1,000,000). FJ has N cows (2 <= N <= 20,000) conveniently numbered 1...N; cow i has length Li (1 <= Li <= 1,000,000). Two cows can fit into the costume if the sum of their lengths is no greater than the length of the costume. FJ wants to know how many pairs of two distinct cows will fit into the costume.

Дадени са n естествени числа. Да се намери броя на двойките числа, чиято сума не надвишава предварително зададено число.


Домашно: Да се използва функция от STL за двоичното търсене и да се сравни ефективността на двете реализации.



INPUT FORMAT:
* Line 1: Two space-separated integers: N and S

* Lines 2..N+1: Line i+1 contains a single integer: Li

SAMPLE INPUT (file costume.in):
4 6
3
5
2
1

OUTPUT FORMAT:
* Line 1: A single integer representing the number of pairs of cows FJ
        can choose. Note that the order of the two cows does not
        matter.

SAMPLE OUTPUT (file costume.out):
4

OUTPUT DETAILS:
The four pairs are as follows: cow 1 and cow 3; cow 1 and cow 4; cow 2 and cow 4; and finally cow 3 and cow 4.

We first sort the heights, using an efficient sort, which takes O(N log N) time. Then, for each height k in the list, we wish to (efficiently) find the index of the largest height that, when added to k, produces a sum less than H. After we find this index, we can count the number of heights that, when added to k, satisfy the given property. The simplest way to find this is with a binary search, which is implemented in the solution below:

#include <algorithm>
#include <cstdio>
using namespace std;

FILE *fout = fopen ("costume.out", "w");
FILE *fin = fopen ("costume.in", "r");

const int MAXN = 20005;
int N, H, total;
int height [MAXN];

// finds the index of the first position whose height is <= value
inline int binsearch (int value)
{
    int lo = 0, hi = N - 1, mid;
    while (lo < hi)
    {
        mid = (lo + hi + 1) >> 1;
        if (height [mid] <= value) lo = mid;
        else hi = mid - 1;
    }
    return lo;
}

int main ()
{
    fscanf (fin, "%d %d", &N, &H);

    for (int i = 0; i < N; i++)
    fscanf (fin, "%d", height + i);

    sort (height, height + N);

    total = 0;
    for (int i = 0; i < N; i++)
    {
    // query the largest index satisfying the conditions
        int ind = binsearch (H - height [i]);

    // only count if ind > i
        if (ind > i) total += ind - i;
        else break;
    }
    fprintf (fout, "%d\n", total);
    return 0;
}