1. 程式人生 > >Financial Aid POJ

Financial Aid POJ

傳送門

題意:奶牛大學為了使得學生選出來的分數中位數最高,並且所選的學生所需的贊助還不能超出預估

題解:首先將所有學生的成績從小到大排序,然後使用優先佇列求出每個位上左邊所要N/2個學生時所需的最小贊助,右邊所要N/2個學生時所需的最小贊助,最後逆序列舉該位上的f1[i]+p[i].c+f2[i]<=F,一旦滿足,直接跳出即可,這個即是滿足條件的答案。

附上程式碼:


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>

using namespace std;

const int maxn=100010;

int N,C,F;

struct node{
    int s,c;
    friend bool operator < (node a,node b){
        return a.c<b.c;
    }
};
node p[maxn];

bool cmp(node a,node b)
{
    return a.s<b.s;
}

priority_queue<node>q1,q2;
int f1[maxn],f2[maxn];

void solve()
{
    sort(p,p+C,cmp);
    int sum1=0,sum2=0;
    int ans=-1;
    memset(f1,0,sizeof(f1));
    memset(f2,0,sizeof(f2));
    for(int i=0;i<C;i++){
        if(i<N/2){
            q1.push(p[i]);
            sum1+=p[i].c;
            continue;
        }
        f1[i]=sum1;
        if(p[i].c>=q1.top().c){
            continue;
        }
        sum1-=q1.top().c;
        q1.pop();
        sum1+=p[i].c;
        q1.push(p[i]);
    }
    for(int i=C-1;i>=0;i--){
        if(i>C-1-N/2){
            q2.push(p[i]);
            sum2+=p[i].c;
            continue;
        }
        f2[i]=sum2;
        if(p[i].c>=q2.top().c){
            continue;
        }
        sum2-=q2.top().c;
        q2.pop();
        sum2+=p[i].c;
        q2.push(p[i]);
    }
    for(int i=C-1-N/2;i>=N/2;i--){
        if(f1[i]+f2[i]+p[i].c<=F){
            ans=p[i].s;
            break;
        }
    }
    printf("%d\n",ans);
}

int main()
{
    while(~scanf("%d%d%d",&N,&C,&F)){
        for(int i=0;i<C;i++){
            scanf("%d%d",&p[i].s,&p[i].c);
        }
        solve();
    }
    return 0;
}