用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;
}
}


京公网安备 11010502036488号