1. 程式人生 > >Wannafly挑戰賽20 B 揹包(貪心)

Wannafly挑戰賽20 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; } } } }