用sum1存储m前半部分的和,sum2存储m后半部分的和。如果m是奇数的话,枚举arr数组,当前位置加上sum1再加上sum2小于等于背包容量,那么这个位置的数就是中位数。如果m是偶数的话,枚举arr数组,当前位置加上sum1再加上sum2小于等于背包容量那么i和i+1的价值和的一半就是中位数,因为i+1的位置在sum2数组中,要想要这个中位数大的话,就尽可能的取sum2中下标靠后的位置,因为sum2的下标越大对应的arr中的val值也就越大(对arr的val升序排序),所以在满足背包容量的前提下找到sum2中位置靠后的位置

#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n, m, v;
const int maxn = 1e5 + 7;
struct node {
    ll val;
    ll weight;
}arr[maxn];
priority_queue<ll>q;
ll sum1[maxn];
ll sum2[maxn];
bool cmp(node a, node b) {
    return a.val < b.val;
}
int main()
{
    cin>>v >> n >> m ;
    for (int i = 1; i <= n; i++) {
        cin >> arr[i].val >> arr[i].weight;
    }
    sort(arr + 1, arr + n + 1, cmp);
    ll num = m >> 1;
    for (int i = 1; i <= n; i++) {
        q.push(arr[i].weight);
        sum1[i] = sum1[i - 1] + arr[i].weight;
        if (q.size() > num - 1 + (m & 1)) {
            sum1[i] -= q.top();
            q.pop();
        }
    }
    while (!q.empty())q.pop();
    for (int i = n; i >= 1; i--) {
        q.push(arr[i].weight);
        sum2[i] = sum2[i + 1] + arr[i].weight;
        if (q.size() > num) {
            sum2[i] -= q.top();
            q.pop();
        }
    }
    if (m & 1) {
        ll ans = 0;
        for (int i = num + 1; i <= n-num; i++) {
            if (sum1[i - 1] + sum2[i + 1] + arr[i].weight <= v)ans = arr[i].val;
        }
        cout << ans;
    }
    else {
        ll ans = 0;
        for (int i = num; i <= n - num; i++) {
            int l = i;
            int r = n - num + 1;
            while (l < r) {
                int mid = (r + l+1) / 2;
                if (sum1[i - 1] + sum2[mid] + arr[i].weight <= v)l = mid;
                else r = mid-1;
            }
           if(r>i) ans = max(ans, arr[i].val + arr[r].val);
        }
        cout << ans / 2;
    }
}