POJ - 2010 优先队列

参考自:https://blog.csdn.net/jhgkjhg_ugtdk77/article/details/38323509

因为是找中位数嘛,所以不必关心这个值的左右到底是谁,只需要知道他可以满足条件即可;

先按照小牛的分数从小到大排个序;

然后我们需要维护这个小牛的左边和右边(n/2)个小牛的最小资助金额;

根据分析,就有了结构体:

struct Cow{

long long val//小牛的分数;

int need//资助金额;

long long lift//表示小牛左边的最小资助金额;

long long right//表示小牛右边的最小资助金额; 

}a[maxn];

最后只需要从大到小枚举 need+lift+right<=f的就可以啦;

用一个优先队列存资助额;

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<utility>
#include<queue>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const double epos=1e-8;

const int maxn=1e5+7;
struct Cow{
    ll val;
    int need;
    ll lift;
    ll right;
}a[maxn];

bool cmp(const Cow& x,const Cow& y){
    return x.val<y.val;
}

priority_queue<int>q;
int main(){
    ll f;
    int n,c;
    int t=0;
    ll val;
    int need;
    scanf("%d%d%lld",&n,&c,&f);
    for(int i=0;i<c;i++){
        scanf("%lld%d",&val,&need);
        if(need<=f){
            a[t].val=val;
            a[t].need=need;
            ++t;
        }
    }
    sort(a,a+t,cmp);
    if(n>1){
        ll sum=0;
        //因为要找中位数,所以开头的n/2个元素肯定是不能选择的;
        for(int i=0;i<n/2;i++){
            sum+=a[i].need;
            q.push(a[i].need);
        }
        //找左边的;
        for(int i=n/2;i<c-n/2;i++){
            a[i].lift=sum;
            int t=a[i].need;
            int hh=q.top();
            if(t<hh){//如果当前的小牛的资助额更小,则更新,方便下一头牛;
                sum=sum-hh+t;
                q.pop();
                q.push(t);
            }
        }

        while(!q.empty()) q.pop();
        sum=0;
        //同上;
        for(int i=c-1;i>=c-n/2;i--){
            sum+=a[i].need;
            q.push(a[i].need);
        }
        //找右边的;
        for(int i=c-n/2-1;i>=n/2;i--){
            a[i].right=sum;
            int t=a[i].need;
            int hh=q.top();
            if(t<hh){
                sum=sum-hh+t;
                q.pop();
                q.push(t);
            }

        }
    }
    
    ll ans=-1;
    for(int i=c-n/2-1;i>=n/2;i--)
        if(a[i].need+a[i].lift+a[i].right<=f){
            ans=a[i].val;
            break;
        }
    printf("%lld\n",ans);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/chenyume/article/details/84174399