https://ac.nowcoder.com/acm/problem/17315
题目描述
Applese有1个容量为v的背包,有n个物品,每一个物品有一个价值a
i,以及一个大小b
i
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装m个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
输入描述:
第一行三个数v, n, m,分别代表背包容量,物品数量以及需要取出的物品数量
接下来n行,每行两个数a
i,b
i,分别代表物品价值以及大小
n ≤ 1e5, 1 ≤ m ≤ n, a
i ≤ 1e9, v ≤ 1e9, b
i ≤ v
输出描述:
仅一行,代表最大的中位数
输入
20 5 3 3 5 5 6 8 7 10 6 15 10
输出
8
题意:
n个物品取m个,容量<=v,求取的m个物品的价值最大中位数是多少?
中位数就是最中间的数,m为奇数即为第m/2+1个,m为偶数即为第(m/2)个和第(m/2+1)个的平均值
题解:
我们可以用优先队列和2个sum数组 分为维护左边m/2个的重量和的最小值 以及右边m/2个的重量和的最小值
如果m为奇数,那我们直接枚举答案就可以
如果m为偶数,我们直接维护左边m/2的重量最小值不是不行的,因为中位数是中间两个数字的平均值,所以我们用优先队列和2个sum数组 分为维护左边m/2-1的重量最小值 以及右边m/2的重量最小值,我们枚举第一个中间的数,第二个中间的数是右边m/2个的最左边的数,因为序列是升序的,我们可以用二分查找最大的右边m/2的最左边的数。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+7; ll sum[maxn],sum2[maxn]; vector < pair<ll ,ll > > a; int main(){ int v,n,m,k; scanf("%d%d%d",&v,&n,&m); ll x,y; a.push_back ( make_pair(0,0)); for(int i=0;i<n;i++){ scanf("%lld%lld",&x,&y); a.push_back ( make_pair(x,y)); } sort(a.begin(),a.end()); priority_queue<ll> p; for(int i=1;i<=n;i++){ p.push(a[i].second); sum[i]=sum[i-1]+a[i].second; if(p.size()>m/2-1+m%2){ sum[i]-=p.top(); p.pop(); } } while(!p.empty()) p.pop(); for(int i=n;i>=1;i--){ p.push(a[i].second); sum2[i]=sum2[i+1]+a[i].second; if(p.size()>m/2 ){ sum2[i]-=p.top(); p.pop(); } } // for(int i=0;i<=n;i++){ // cout<<a[i].first<<" "<<a[i].second<<endl; // } // for(int i=0;i<=n;i++){ // cout<<sum[i]<<" "; // } // cout<<endl; // for(int i=0;i<=n;i++){ // cout<<sum2[i]<<" "; // } ll ans=0; if(m&1){ for(int i=m/2;i<=n-m/2;i++){ if(sum[i-1]+sum2[i+1]+a[i].second<=v) ans=a[i].first; } cout<<ans<<endl; }else{ for(int i=m/2;i<=n-m/2;i++){ int l=i+1,r=n-m/2+1; while(l<=r){ int mid=(l+r)>>1; if(sum[i-1]+sum2[mid]+a[i].second<=v) l=mid+1; else r=mid-1; } if(r>i) ans=max(ans,1ll+a[i].first+a[r].first-1); } cout<<ans/2<<endl; } return 0; } /* 20 5 4 3 5 5 4 8 5 10 4 15 6 */