luogu 3045 优先队列反悔/bzoj 2590
N头奶牛,价格Pi,K张优惠券,优惠券购买降为Ci,不超过M的钱最多可买多少奶牛
先将c值k小的加入,将它们省下的钱加入优先队列(省下的钱由少到多),在将k+1-n用p排序,再逐个与优先队列中弹出的比较
若省下的钱更多则赎回优惠券买这个(c+以前的p-c),否则买下全票p
不过这题的贪心其实有些奇怪,还是不太能想来
#include <bits/stdc++.h> #define rep(i,j,k) for(int i=j;i<=k;i++) #define N 50010 #define inf 0x3fffffff #define LL long long using namespace std; inline LL read(){ LL x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;} struct nd{int p,c,k;}a[N];int n,k;LL m,sum; priority_queue<int,vector<int>,greater<int> >q; bool cmp1(nd a,nd b){return a.c<b.c;} bool cmp2(nd a,nd b){return a.p<b.p;} int main(){ // freopen("2590.in","r",stdin); // freopen("2590.out","w",stdout); n=read(),k=read(),m=read(); rep(i,1,n)a[i].p=read(),a[i].c=read(),a[i].k=a[i].p-a[i].c; sort(a+1,a+1+n,cmp1);rep(i,1,k){ sum+=a[i].c;if(sum>m){printf("%d",i-1);return 0;} if(i==n){printf("%d",n);return 0;} q.push(a[i].k);} sort(a+1+k,a+1+n,cmp2);rep(i,k+1,n){ int t=q.empty()?inf:q.top(); if(a[i].k>t){sum=sum+t+a[i].c;q.pop(); q.push(a[i].k);}else sum+=a[i].p; if(sum>m){printf("%d",i-1);return 0;} if(i==n){printf("%d",n);return 0;}} return 0; }