Wannafly挑戰賽20 B 揹包(貪心)
阿新 • • 發佈:2019-01-25
題目描述
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;
}
}
}
}