由题意可知,饭局的隔阂值为隔阂最大的那一对朋友的隔阂,也就是所有参与饭局的朋友中财富最大的减去财富最小的。根据贪心的思想,如果邀请了其中两名成员和,那么想要让愉悦值最大,应当尽可能多的邀请财富值在两者之间的其他朋友。

将所有成员按照财富从小到大排序,就可以将题目转化为求连续区间的愉悦值之和大于等于k的情况下,首尾元素财富值之差的最小值。我们很容易想到用前缀和与双指针的思想来解题。

我们维护一个愉悦值的前缀和数组sum,那么连续区间[l, r]的愉悦值之和为sum[r] - sum[l-1]。

双指针的处理就很简单了,具体处理方法直接看代码吧。

统计下时间复杂度:排序O(nlogn),计算前缀和数组O(n),双指针遍历O(n)。

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

struct py {
    int a, b;
};

int main() {
    int n;
    long long k;
    cin >> n >> k;
    vector<py> vec(n);
    for (py& p : vec) {
        cin >> p.a;
    }
    for (py& p : vec) {
        cin >> p.b;
    }
    sort(vec.begin(), vec.end(), [&](py p1, py p2) {
        return p1.a < p2.a;
    });
    vector<long long> sum(n + 1); // 前缀和 sum[i]表示0~i-1的愉悦值之和
    sum[0] = 0;
    for (int i = 1; i <= n; ++i) {
        sum[i] = sum[i - 1] + vec[i - 1].b;
    }
    if (sum[n] < k) { //判断k无法满足的情况输出-1
        cout << -1;
        return 0;
    }
    int ans = 1e9;
    int l = 0, r = 1;
    while (r <= n) {
        //右指针移动,直到愉悦值之和达到k为止
        while (r <= n && sum[r] - sum[l] < k) {
            ++r;
        }
        if (r > n) break;//超出界限跳出
        while (sum[r] - sum[l] >= k) {
            ++l; //左指针移动,直至愉悦值之和不满足k为止
        }
        --l; //左指针跳回上一个满足k的位置,此时得到一个最小区间,更新ans
        ans = min(ans, vec[r - 1].a - vec[l].a);
        ++l; //左指针移动一格,搜索下一个最小区间
    }
    cout << ans;
}
// 64 位输出请用 printf("%lld")