Descrption
Input
Output
Sample Input
3 5 70 
30 25 
50 21 
20 20 
5 18 
35 30
Sample Output
35
Hint
猪仙接受 \(CSAT\) 分数为 \(5,35,50\) 的猪的申请,中位数为 \(35\),需支付的奖学金总额为 \(18+30+21=69≤70\) 。
分析
Code
#include <bits/stdc++.h>
const int maxn=2e5+5;
int n,c,F;
std::priority_queue <int> q;
struct Node{
    int s,w;//分数,奖金
} a[maxn];
bool cmp(const Node &a, const Node &b){
    return a.s<b.s;
}
int f[maxn],g[maxn],sum;;
void Init(){
    scanf("%d%d%d", &n,&c,&F);
    for(int i=1;i<=c;++i)
        scanf("%d%d", &a[i].s,&a[i].w);
    std::sort(a+1,a+1+c,cmp);//按成绩升序
}
void Solve(){
    for(int i=1;i<=n/2;++i){//成绩最低的n/2进入队列
        sum+=a[i].w;//累加总奖金
        q.push(a[i].w);//队列是维护奖金的大根堆
    }
    //f[i]:表示以i为中位数前n/2人的最小奖金
    for(int i=n/2+1;i<=c;++i){
        f[i]=sum;
        int top=q.top();
        if(top>a[i].w){//如果当前的奖金小于堆顶则交换掉
            q.pop();
            sum-=top;
            sum+=a[i].w;
            q.push(a[i].w);
        }
    }
    sum=0;
    while(!q.empty()) q.pop();
    for(int i=c;i>=c-n/2+1;--i){//成绩最高的n/2进入队列
        sum+=a[i].w;
        q.push(a[i].w);
    }
    //g[i]:表示以i为中位数后n/2人的最低奖金
    for(int i=c-n/2;i>=1;--i){
        g[i]=sum;
        int top=q.top();
        if(top>a[i].w){//交换
            q.pop();
            sum-=top;
            sum+=a[i].w;
            q.push(a[i].w);
        }
    }
    //中位数的取值范围是[n/2+1,c-n/2]
    //因为要求最大中位数,所以倒序
    for(int i=c-n/2;i>=n/2+1;--i)
        if(a[i].w+f[i]+g[i]<=F){
            printf("%d", a[i].s);
            return;
        }
    printf("-1\n");
}
int main(){
    Init();
    Solve();
    return 0;
}
原文:https://www.cnblogs.com/hbhszxyb/p/13201902.html