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;
}

猜你喜欢

转载自www.cnblogs.com/asdic/p/9668402.html