zoukankan      html  css  js  c++  java
  • bzoj2590[Usaco2012 Feb]Cow Coupons

    题意

    FJ准备买一些新奶牛,市场上有N头奶牛(1<=N<=50000),第i头奶牛价格为Pi(1<=Pi<=10^9)。FJ有K张优惠券,使用优惠券购买第i头奶牛时价格会降为Ci(1<=Ci<=Pi),每头奶牛只能使用一次优惠券。FJ想知道花不超过M(1<=M<=10^14)的钱最多可以买多少奶牛?

    分析

    比别人多个log系列...
    答案显然有可二分性.所以先二分答案m,求购买m头牛的最小花费.
    考虑先确定买哪些奶牛再确定这些奶牛中哪些用优惠券.如果已经知道了买哪些奶牛,对于每一头牛使用优惠券的收益Pi-Ci是确定的,我们把Pi-Ci排个序,获得其中最大的k个收益即可.也就是说,最后一定是Pi-Ci较大的一些牛使用优惠券.
    因此我们把n头奶牛按照Pi-Ci从小到大排序.对于最优方案,一定存在一个分界点使得分界点左侧的牛要么不选要么付出Pi的代价,分界点右侧的牛要么不选要么付出Ci的代价.
    然后枚举分界点,维护分界点左侧最小的m-k个Pi和分界点右侧最小的k个Ci,就可以求出最小花费.我写了一发multiset.
    复杂度(O(nlog^{2}n))
    终于学会multiset在存在多个相同元素时怎样只删除其中一个而不删除其他相同元素了,传迭代器进去即可

    你可能看了假的C++选手写的题解

    #include <cstdio>
    #include <set>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=50005;
    int n,k;ll money;
    ll p[maxn],c[maxn];
    int seq[maxn];
    bool cmpdlt(const int &a,const int &b){
      return p[a]-c[a]<p[b]-c[b];
    }//left: p right: c
    bool cmpc(const int &a,const int &b){
      return c[a]<c[b];
    }
    int seq2[maxn];
    bool check(int m){
      if(m==0)return true;
      if(m<=k){
        long long sum=0;
        for(int i=1;i<=m;++i){
          sum+=c[seq2[i]];
        }
        return sum<=money;
      }else{
        ll ans=1ll<<60;
        int g=m-k;//g cows without coupon,k cows with coupon
        multiset<ll> lbuy,rbuy,lnot,rnot;
        ll lsum=0,rsum=0;
        for(int i=1;i<=g;++i){
          lsum+=p[seq[i]];
          lbuy.insert(p[seq[i]]);
        }
        int cnt=0;
        for(int i=g+1;i<=n;++i){
          if(cnt<k){
    	rsum+=c[seq[i]];rbuy.insert(c[seq[i]]);
    	++cnt;
          }else{
    	if(c[seq[i]]<(*rbuy.rbegin())){
    	  rsum-=(*rbuy.rbegin());
    	  rsum+=c[seq[i]];
    	  rnot.insert((*rbuy.rbegin()));
    	  rbuy.erase(--rbuy.end());
    	  rbuy.insert(c[seq[i]]);
    	}else{
    	  rnot.insert(c[seq[i]]);
    	}
          }
        }
        ans=min(ans,lsum+rsum);
        for(int i=g+1;i<=n-k;++i){
          if(p[seq[i]]<(*lbuy.rbegin())){
    	lsum-=*lbuy.rbegin();
    	lbuy.erase(--lbuy.end());
    	lsum+=p[seq[i]];lbuy.insert(p[seq[i]]);
          }
          if(rbuy.find(c[seq[i]])!=rbuy.end()){
    	rsum-=c[seq[i]];
    	rbuy.erase(rbuy.find(c[seq[i]]));
    	rsum+=(*rnot.begin());rbuy.insert(*rnot.begin());
    	rnot.erase(rnot.begin());
          }
          ans=min(ans,lsum+rsum);      
        }
        return ans<=money;
      }
    }
    int main(){
      scanf("%d%d%lld",&n,&k,&money);
      for(int i=1;i<=n;++i)scanf("%lld%lld",p+i,c+i);
      for(int i=1;i<=n;++i)seq[i]=i,seq2[i]=i;
      sort(seq+1,seq+n+1,cmpdlt);sort(seq2+1,seq2+n+1,cmpc);
      int l=0,r=n;
      while(l<=r){
        int mid=(l+r)>>1;
        if(check(mid))l=mid+1;
        else r=mid-1;
      }
      printf("%d
    ",l-1);
      return 0;
    }
    
    
  • 相关阅读:
    新浪微博千万级规模高性能、高并发的网络架构经验分享
    PHP- 如何在终端输出带颜色的字体?
    淘宝大秒杀系统是如何设计的?
    如何打造千万级Feed流系统
    Redis实现分布式锁 php
    Ubuntu16.04 安装PHP7 的 imagick 扩展
    nginx配置http访问自动跳转到https
    使用Redis来实现LBS的应用
    PHP多进程编程初步
    选redis还是memcache,源码怎么说
  • 原文地址:https://www.cnblogs.com/liu-runda/p/7158529.html
Copyright © 2011-2022 走看看