链接: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
题解:
对于偶数,我是暴力中间靠左边的数,,直接二分查找右端即可。
#include<queue>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define ll long long
int n,m,v;
ll sum[100005],sum1[100005],ans,dp[100005];
priority_queue<int>q,q1,qq;
struct node
{
int w,v,id;
}a[100005];
bool comp(node a,node b)
{
if(a.v==b.v)
return a.w<b.w;
return a.v<b.v;
}
int main(void)
{
scanf("%d%d%d",&v,&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].v,&a[i].w);
sort(a+1,a+n+1,comp);
for(int i=1;i<=(m-1)/2;i++)
q.push(a[i].w),sum[(m-1)/2]+=a[i].w;
for(int i=(m-1)/2+1;i<=n;i++)
{
sum[i]=sum[i-1];
if(a[i].w>q.top())
continue;
sum[i]-=q.top();q.pop();
q.push(a[i].w);sum[i]+=a[i].w;
}
for(int i=n;i>n-(m-1)/2;i--)
q1.push(a[i].w),sum1[n-(m-1)/2+1]+=a[i].w;
for(int i=n-(m-1)/2;i>0;i--)
{
sum1[i]=sum1[i+1];
if(a[i].w>q1.top())
continue;
sum1[i]-=q1.top();q1.pop();
q1.push(a[i].w);sum1[i]+=a[i].w;
}
if(m%2)
{
for(int i=(m-1)/2+1;i<=n-(m-1)/2;i++)
if(sum[i-1]+sum1[i+1]+a[i].w<=v)
ans=max(ans,(ll)a[i].v);
printf("%lld\n",ans);
}
else
{
for(int i=(m-1)/2+1;i<=n-(m-1)/2-1;i++)
{
int l=i+1,r=n-(m-1)/2,mid,p=-1;
while(l<=r)
{
mid=(l+r)/2;
if(sum[i-1]+sum1[mid+1]+a[i].w+a[mid].w<=v)
p=mid,l=mid+1;
else
r=mid-1;
}
if(p>0) ans=max(ans,(ll)(a[i].v+a[p].v));
}
printf("%lld\n",ans/2);
}
return 0;
}