zoukankan      html  css  js  c++  java
  • Moo University

    题意:

    在C头牛里选N头牛,每头牛需要花掉一定经费ai才能得到一定得bi分,在不超过经费F的情况下,使得N头牛的得分中位数最大。(1 <= N <= 19,999,奇数) (N <= C <= 100,000)(0 <= F <= 2,000,000,000)

    输入:(N,C,F;ai,bi)

    3 5 70
    30 25
    50 21
    20 20
    5 18
    35 30
    
    输出:
       35
    分析:
    最朴素的办法:按分数从小到大排列,枚举原点,从右到左扫,区间为[(m+1)/2,n-(m+1)/2],计算左边最小和和右边最小和,判断是否是满足条件,满足即输出。
    显然这种n2的办法是不行的。
    我们要减复杂度,就要在枚举原点的同时维护左右两边最小和,如何维护?
    方法一(较复杂,但是是一个解决问题的想法):
    针对右边,我们的需求是:不断加入值,求前k小的和。我们建立一个大根堆,并在开始的时候记录一个sumR,每加入一个点,如果小于大根堆顶,便更新sumR,弹出堆顶,压入新点。
    针对左边,我们的需求是:不断删去值,求前k小的和这个方法就困难在这里,我们在区间[1,(2n-m-1)/2]新建立一个数组new,按花销从小到大排序,同样时原位置小的在前,同时记录该点是否要去除(usd)。什么意思呢?我们最开始在原数组统计的和sumL=sum(1->(m-1)/2),并在(m-1)/2处设立一个指针p。在原数组删去一个数的时候,如果在new对应的位置在p右边则不用管,标记usd=1。如果在p位置或p位置的左边,就在sumL删除这个数,p向右移至第一个usd没被标记的地方,sumL加入这个新数。
    方法二:
    我们发现不断删去值,求前k小的和要比不断加入值,求前k小的和更加困难,那我们就提前从左向右扫一边,那么针对左边,就是和右边一样的需求了(不断加入值,求前k小的和)。
    这道题还是费了我一点脑子的...
     
    代码:
     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<iostream>
     9 #include<algorithm>
    10 #define RG register int
    11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
    12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
    13 #define ll long long
    14 #define inf (1<<29)
    15 #define maxn 100005
    16 using namespace std;
    17 int n,m,F,L,R,rt;
    18 int sL,sR;
    19 int po[maxn];
    20 struct D{
    21     int cost,sco;
    22     inline int operator < (const D &tmp)const{
    23         return sco<tmp.sco;
    24     }
    25 }a[maxn];
    26 struct Dat{
    27     int val,id,usd;
    28     inline int operator < (const Dat &tmp)const{
    29         return (val==tmp.val)?id<tmp.id:val<tmp.val;
    30     }
    31 }b[maxn];
    32 priority_queue<int> que;
    33 inline int read()
    34 {
    35     int x=0,f=1;char c=getchar();
    36     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    37     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    38     return x*f;
    39 }
    40 
    41 void work()
    42 {
    43     L=(m+1)/2,R=n-(m-1)/2;
    44     
    45     int end=(2*n-m+3)/2;
    46     per(i,n,end)    que.push(a[i].cost),sR+=a[i].cost;
    47     
    48     
    49     end=(2*n-m-1)/2,rt=(m-1)/2;
    50     rep(i,1,end)    b[i].val=a[i].cost,b[i].id=i;
    51     sort(b+1,b+1+end);
    52     rep(i,1,end)    po[b[i].id]=i;
    53     rep(i,1,rt)        sL+=b[i].val;
    54     
    55     end=(2*n-m+3)/2;
    56     per(O,R,L)
    57     {
    58         if(sL+sR+a[O].cost<=F)    {printf("%d
    ",a[O].sco);return;}
    59         
    60         if(a[O].cost<que.top())    sR-=que.top()-a[O].cost,que.pop(),que.push(a[O].cost);
    61         
    62         b[po[O-1]].usd=1;
    63         if(po[O-1]<=rt)
    64         {
    65             while(b[rt].usd&&rt<=end)    rt++;
    66             if(rt==(2*n-m+5)/2)    {puts("-1");return;}
    67             sL+=b[rt].val-a[O-1].cost;
    68         }
    69     }
    70     puts("-1");return;
    71 }
    72 
    73 void dif()
    74 {
    75     per(i,n,1)
    76         if(a[i].cost<=F){printf("%d
    ",a[i].sco);return;}
    77     exit(0);
    78     
    79 }
    80 
    81 int main()
    82 {
    83     m=read(),n=read(),F=read();
    84     rep(i,1,n)    a[i].sco=read(),a[i].cost=read();
    85     sort(a+1,a+1+n);
    86     L=(m+1)/2,R=n-(m-1)/2;
    87     if(m==1)    dif();
    88     else         work();
    89     return 0;
    90 }
    View Code
     
  • 相关阅读:
    将所有程序设置XML集中到一个单独XML配置文件的方法:使用appSettings元素的configSource元素
    MVC中JQuery文件引入的路径问题,@Url.Content函数
    EF的表连接方法Include()
    在使用EFCodeFirst中出现类型“System.Data.Objects.ObjectContext”在未被引用的程序集中定义的解决方案
    总结下遇到的C#新语法
    MVC3下的layout页面
    C#委托初探
    WebBrowser Control
    Python之面向对象二
    Python之面向对象一
  • 原文地址:https://www.cnblogs.com/ibilllee/p/9221758.html
Copyright © 2011-2022 走看看