【贪心】【堆】bzoj2590 [Usaco2012 Feb]Cow Coupons
每个物品有属性a,b
考虑在仅仅用光优惠券时的最优方案。
显然是按照b排序,取前K个。
但是我们还要尽可能去取剩余的。
假设朴素地取剩余的话,应该把剩余的对a排序,然后尽量去取。
但是有可能对其用优惠券,而对之前的某个不用优惠券,比原来优,这时我们就要更新用优惠券的物品集合。
对a-b的差值用堆维护即可。
#include<cstdio> #include<queue> #include<algorithm> #include<iostream> using namespace std; struct data{ int a,b; }a[50010]; bool cmp(const data &a,const data &b){ return a.b<b.b; } bool cm2(const data &a,const data &b){ return a.a<b.a; } typedef long long ll; priority_queue<int,vector<int>,greater<int> >q; int n,K; ll m,sum; int main(){ cin>>n>>K>>m; for(int i=1;i<=n;++i){ scanf("%d%d",&a[i].a,&a[i].b); } sort(a+1,a+n+1,cmp); for(int i=1;i<=K;++i){ sum+=(ll)a[i].b; q.push(a[i].a-a[i].b); if(sum>m){ printf("%d\n",i-1); return 0; } } sort(a+K+1,a+n+1,cm2); for(int i=K+1;i<=n;++i){ if(a[i].a-a[i].b<=q.top()){ sum+=(ll)a[i].a; } else{ sum+=(ll)q.top(); q.pop(); q.push(a[i].a-a[i].b); sum+=(ll)a[i].b; } if(sum>m){ printf("%d\n",i-1); return 0; } } printf("%d\n",n); return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/