zoukankan      html  css  js  c++  java
  • 【优先队列】POJ2010- Moo University-Financial Aid

    【题目大意】

    给出C头奶牛的SAT成绩和申请奖学金,选出N头牛,使得总奖学金在≤F的情况下奶牛SAT成绩的中位数最大。

    【思路】

    假设before[i]表示前i头奶牛中n/2头奶牛奖学金总额的最小值,而after[i]表示后i头奶牛中n/2头奶牛奖学金总额的最小值。

    将C头奶牛按照SAT成绩进行排序后,从第c-n/2头开始到第n/2+1头奶牛进行枚举,如果当前before[i]+after[i]+当前奶牛申请的奖学金≤F,则退出,当前奶牛SAT成绩就是中位数的最大值。那么如何求before和after呢?可以用优先队列进行预处理。

    以before为例,每新加入一头奶牛,就把它申请的奖学金累加到sum中去。如果当前优先队列的size大于n/2,则让队首(即申请奖学金最多的那一个)出队。这样,sum的总和始终未前i头奶牛中,n/2头奶牛奖学金总和的最小值。after同理从后往前做即可。

    【错误点】

    不要忘记了有可能是无解的,要输出-1;其次由于数组下标是0开始的,注意循环是[c-1-n/2,n/2]。

    看discuss区有人说有多组数据,不写while会出错。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<algorithm>
     5 using namespace std;
     6 const int MAXC=100000+50;
     7 struct node
     8 {
     9     int csat,req;
    10     bool operator < (const node &x) const
    11     {
    12         return csat<x.csat;
    13     }
    14 }cow[MAXC];
    15 int n,c,f;
    16 
    17 int before[MAXC],after[MAXC];
    18 
    19 void pretreatment()
    20 {
    21     priority_queue<int> be,af;
    22     int sum=0;
    23     for (int i=0;i<c;i++)
    24     {
    25         be.push(cow[i].req);
    26         sum+=cow[i].req;
    27         if (be.size()>n/2)
    28         {
    29             sum-=be.top();
    30             be.pop();
    31         }
    32         if (be.size()<n/2) before[i]=0;
    33             else before[i]=sum;
    34     }
    35     
    36     sum=0;
    37     for (int i=c-1;i>=0;i--)
    38     {
    39         af.push(cow[i].req);
    40         sum+=cow[i].req;
    41         if (af.size()>n/2)
    42         {
    43             sum-=af.top();
    44             af.pop();
    45         }
    46         if (af.size()<n/2) after[i]=0;
    47             else after[i]=sum;
    48     }
    49 }
    50 
    51 void getans()
    52 {
    53     int i,boolf=0;
    54     for (i=c-1-n/2;i>=n/2;i--)
    55     {
    56         if (before[i-1]+after[i+1]+cow[i].req<=f) 
    57         {
    58             boolf=1;
    59             break;
    60         }
    61     }
    62     if (boolf==1) 
    63         cout<<cow[i].csat<<endl;
    64         else cout<<-1<<endl;
    65 }
    66 
    67 int main()
    68 {
    69     while (scanf("%d%d%d",&n,&c,&f)!=EOF)
    70     {
    71         for (int i=0;i<c;i++) scanf("%d%d",&cow[i].csat,&cow[i].req);
    72         sort(cow,cow+c);
    73     
    74         pretreatment();
    75         getans();
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    CF687D Dividing Kingdom II
    图论——EK算法
    P6082 [JSOI2015]salesman
    联合权值——树上问题2014noip
    P2071 座位安排——二分图最大匹配
    匈牙利优化时间戳的正确性
    P1541 乌龟棋——线性动规
    P1858 多人背包
    P3558 [POI2013]BAJ-Bytecomputer——线性动归
    P2303 [SDOI2012] Longge 的问题
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/4738644.html
Copyright © 2011-2022 走看看