题目大意\(:\)给出\(N\)个整数和一个整数\(M\),求\(N\)个数中差值最小且相加等于\(M\)的两个数。

看到差值最小,我们首先想到排序,二分,实际上这也就是本题的正解解法了。

首先我们对题目给出的\(N\)个整数进行排序,使整个序列变得单调,然后我们二分查找出第一个大于\(M/2\)的位置\(pos\),然后设\(l=pos-1,r=pos\),然后分别向左向右扩展\(:\)

  • \(d[l] + d[r] < M, r++;\)
  • \(d[l] + d[r] > M, l--;\)
  • \(d[l] + d[r] == M,\)输出答案即可。

最后一点\(:\)此题继承了\(UVA\)的优良传统,读入和输出很毒瘤,最后输出的时候一定要记得加两个换行符\(……\)

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

const int maxn = 1e4 + 5;
int n, d[maxn], goal;

int main() {
    while (scanf("%d\n", &n) != EOF) {
        for (int i = 1; i <= n; i++)
            scanf("%d", &d[i]);
        scanf("%d", &goal);
        std::sort(d + 1, d + n + 1);
        int pos = std::upper_bound(d + 1, d + n + 1, goal / 2) - d; // upper_bound找出第一个大于M/2的数
        // 具体upper_bound用法不懂得小伙伴可以自行百度
        if (pos >= 2 && d[pos - 1] + d[pos - 2] == goal)  //一个小小的优化
            printf("Peter should buy books whose prices are %d and %d.\n\n", d[pos - 2], d[pos - 1]);
        else {
            int l = pos - 1, r = pos;
            while (l > 0 && r <= n) {
                if (d[l] + d[r] == goal) {
                    printf("Peter should buy books whose prices are %d and %d.\n\n", d[l], d[r]);
                    // 毒瘤的输出
                    break;
                }
                else if (d[l] + d[r] > goal)
                    l--;
                else r++;
            }
        }
    }
    return 0;
}

完结撒花(✪ω✪)

12-31 15:03