• [USACO12FEB]牛券Cow Coupons(堆,贪心)


    [USACO12FEB]牛券Cow Coupons(堆,贪心)

    题目描述

    Farmer John needs new cows! There are N cows for sale (1 <= N <= 50,000), and FJ has to spend no more than his budget of M units of money (1 <= M <= 10^14). Cow i costs P_i money (1 <= P_i <= 10^9), but FJ has K coupons (1 <= K <= N), and when he uses a coupon on cow i, the cow costs C_i instead (1 <= C_i <= P_i). FJ can only use one coupon per cow, of course.

    What is the maximum number of cows FJ can afford?

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

    输入输出格式

    输入格式:

    • Line 1: Three space-separated integers: N, K, and M.

    • Lines 2..N+1: Line i+1 contains two integers: P_i and C_i.

    输出格式:

    • Line 1: A single integer, the maximum number of cows FJ can afford.

    输入输出样例

    输入样例#1:

    4 1 7
    3 2
    2 2
    8 1
    4 3

    输出样例#1:

    3

    说明

    FJ has 4 cows, 1 coupon, and a budget of 7.

    FJ uses the coupon on cow 3 and buys cows 1, 2, and 3, for a total cost of 3 + 2 + 1 = 6.

    堆模拟反悔操作

    很容易发现直接贪心是错误的,因为我们有总钱数的限制。
    那么我们可不可以通过调整假的贪心策略来获得正确答案呢?
    先贪心地拿最小的k个优惠价,然后考虑怎么反悔。
    对于两头牛(i,j),假设(i)用了优惠券,(j)没有用,什么情况下会使(j)用优惠券(i)不用更优呢?很简单:(c[i]+p[j]>p[i]+c[j])。用一个堆维护用优惠券的牛,令一个堆维护还未选择的牛。每次考虑未选择的牛是用原价买还是“反悔”。
    不过自己还有一个疑问,每次钱不够的时候就能够break掉了吗?感觉仔细思考了一下并不可以。希望能够解答

    #include<bits/stdc++.h>
    #define lll long long
    using namespace std;
    lll read(){
        lll x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*w;
    }
    const lll N=50010;
    lll n,k,m,ans;
    bool vis[N];
    struct node{
        lll p,c,v;
    }f[N];
    priority_queue< pair<int,int> >q1,q2;
    bool cmp(node p,node q){return p.c<q.c;}
    int main(){
        n=read();k=read();m=read();
        for(lll i=1;i<=n;i++)f[i].p=read(),f[i].c=read(),f[i].v=f[i].p-f[i].c;
        sort(f+1,f+1+n,cmp);
        for(lll i=1;i<=k;i++){
            if(m<f[i].c){cout<<i-1;return 0;}
            m-=f[i].c;q1.push(make_pair(f[i].v,i));
        }ans=k;
        for(lll i=k+1;i<=n;i++)q2.push(make_pair(-f[i].p,i));
        while(m&&ans!=n){
            lll i=q2.top().second;q2.pop();
            lll j=q1.top().second;q1.pop();
            if(f[j].c+f[i].p>f[i].c+f[j].p){
                if(m<f[j].v+f[i].c)break;
                q1.push(make_pair(f[i].v,i));
                m-=f[j].v+f[i].c;ans++;
            }
            else {
                if(m<f[i].p)break;
                q1.push(make_pair(f[j].v,j));
                m-=f[i].p;ans++;
            }
        }cout<<ans<<endl;
    }
    
  • 相关阅读:
    Linux(CentOS 7)命令行模式安装VMware Tools 详解
    最全面的移动APP测试点
    利用Fiddler编写Jmeter接口测试
    LeetCode | TwoSum
    Python
    Django
    浅谈web网站架构演变过程
    Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解
    Web服务器之Nginx详解(操作部分)
    Web服务器之Nginx详解(理论部分)
  • 原文地址:https://www.cnblogs.com/lsgjcya/p/9746268.html
Copyright © 2020-2023  润新知