链接:https://www.nowcoder.com/acm/contest/133/B
来源:牛客网
题目描述
Applese有1个容量为v的背包,有n个物品,每一个物品有一个价值ai,以及一个大小bi
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
输入描述:
第一行三个数v, n, m,分别代表背包容量,物品数量以及需要取出的物品数量
接下来n行,每行两个数ai,bi,分别代表物品价值以及大小
n ≤ 1e5, 1 ≤ m ≤ n, ai ≤ 1e9, v ≤ 1e9, bi ≤ v
输出描述:
仅一行,代表最大的中位数
示例1
输入
复制
20 5 3
3 5
5 6
8 7
10 6
15 10
输出
复制
8
按价值排序然后分奇偶讨论就好了
用优先队列维护下就行了
accode
#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5+32;
struct node
{
LL v,cost;
bool operator <(const node& p) const{
if(v==p.v){
return cost<p.cost;
}
return v<p.v;
}
}Q[maxn];
LL n,m,v;
int dp1[maxn];
int dp2[maxn];
int main()
{
scanf("%lld%lld%lld",&v,&n,&m);
for(int i = 1;i<=n;i++){
scanf("%lld%lld",&Q[i].v,&Q[i].cost);
}
sort(Q+1,Q+n+1);
priority_queue<LL>pq;
if(m%2){
//cout<<"ffw"<<endl;
LL sum = 0;
int cnt = m/2;
for(int i = 1;i<=n;i++){
dp1[i] = sum;
pq.push(Q[i].cost);
sum+=Q[i].cost;
if(pq .size()>cnt){
LL tmp = pq.top();
pq.pop();
sum -= tmp;
}
}
while(pq.size()) pq.pop();
sum = 0;
for(int i = n;i>=1;i--){
dp2[i] = sum;
pq.push(Q[i].cost);
if(pq.size()>cnt){
LL tmp = pq.top();
pq.pop();
sum -= tmp;
}
sum+=Q[i].cost;
}
for(int i = n-cnt;i>cnt;i--){
if(dp1[i]+dp2[i]+Q[i].cost<=v){
// cout<<dp1[i]<<' '<<dp2[i]<<' '<<i<<endl;
cout<<Q[i].v<<endl;
return 0;
}
}
}
else{
LL sum = 0;
int cnt = m/2;
for(int i = 1;i<=n;i++){
pq.push(Q[i].cost);
sum+=Q[i].cost;
if(pq .size()>cnt){
LL tmp = pq.top();
pq.pop();
sum -= tmp;
} dp1[i] = sum;
}
while(pq.size()) pq.pop();
sum = 0;
for(int i = n;i>=1;i--){
pq.push(Q[i].cost);
sum+=Q[i].cost;
if(pq.size()>cnt){
LL tmp = pq.top();
pq.pop();
sum -= tmp;
} dp2[i] = sum;
}
for(int i = n-cnt;i>=cnt;i--){
if(dp1[i]+dp2[i+1]<=v){
cout<<(Q[i].v+Q[i+1].v)/2<<endl;
return 0;
}
}
}
}