洛谷 P4181 [USACO18JAN]Rental Service

题意翻译

farmer john有N(1≤N≤100,000)头牛,他想赚跟多的钱,所以他准备买牛奶和出租牛。有M(1≤M≤100,000 )家商店想买牛奶,每家商店的进货价不同。有R(1≤R≤100,000 )户邻居想租牛,每户人家的租价不同。 问他最多能赚多少钱。

输入:输入的第1行包含n,m,r三个整数。紧接着的n行每一行有1个整数Ci (1≤Ci≤1,000,000),表示第i头牛产出Ci加仑奶。再下面的m行每行有两个整数Qi与Pi (1≤Qi,Pi≤1,000,000),表示第i个商店最多以Pi美分每加仑的价格购买Qi加仑牛奶。FJ可销售0~Qi加仑牛奶到一个商店。然后的r行每行有一个整数Ri,表示FJ的第i个邻居想以Ri(1≤Ri≤1,000,000 ), 的价格租一头牛。

输出:仅一行。表示一天最多获得多少钱。

注意:int类型不够大!!!

说明: FJ 需要挤一号和四号奶牛的奶,共可得牛奶13加仑。他可以先买给出价最高的10加仑,赚250美分,然后把剩下的按每加仑15美分去卖,共有295美分的利润。 然后,他要把其他三头以250,80,和100美分的价格分别卖出,赚430美分。所以他一共可得725美分/日的利润。

---by 风格雨关、WuYongxuan、毕沁露

题目描述

Farmer John realizes that the income he receives from milk production is insufficient to fund the growth of his farm, so to earn some extra money, he launches a cow-rental service, which he calls "USACOW" (pronounced "Use-a-cow").

Farmer John has NNN cows (1≤N≤100,0001 \leq N \leq 100,0001≤N≤100,000), each capable of producing some amount of milk every day. The MMM stores near FJ's farm (1≤M≤100,0001 \leq M \leq 100,0001≤M≤100,000) each offer to buy a certain amount of milk at a certain price. Moreover, Farmer John's RRR (1≤R≤100,0001 \leq R \leq 100,0001≤R≤100,000) neighboring farmers are each interested in renting a cow at a certain price.

Farmer John has to choose whether each cow should be milked or rented to a nearby farmer. Help him find the maximum amount of money he can make per day.

输入输出格式

输入格式:

 

The first line in the input contains NNN, MMM, and RRR. The next NNN lines each contain an integer cic_ici​ (1≤ci≤1,000,0001 \leq c_i \leq 1,000,0001≤ci​≤1,000,000), indicating that Farmer John's iiith cow can produce cic_ici​ gallons of milk every day. The next MMM lines each contain two integers qiq_iqi​ and pip_ipi​ (1≤qi,pi≤1,000,0001 \leq q_i, p_i \leq 1,000,0001≤qi​,pi​≤1,000,000), indicating that the iiith store is willing to buy up to qiq_iqi​ gallons of milk for pip_ipi​ cents per gallon. Keep in mind that Farmer John can sell any amount of milk between zero and qiq_iqi​ gallons to a given store. The next RRR lines each contain an integer rir_iri​ (1≤ri≤1,000,0001 \leq r_i \leq 1,000,0001≤ri​≤1,000,000), indicating that one of Farmer John's neighbors wants to rent a cow for rir_iri​ cents per day.

 

输出格式:

 

The output should consist of one line containing the maximum profit Farmer John can make per day by milking or renting out each of his cows. Note that the output might be too large to fit into a standard 32-bit integer, so you may need to use a larger integer type like a "long long" in C/C++.

 

输入输出样例

输入样例#1:

5 3 4
6
2
4
7
1
10 25
2 10
15 15
250
80
100
40

输出样例#1:

725

说明

Farmer John should milk cows #1 and #4, to produce 13 gallons of milk. He should completely fill the order for 10 gallons, earning 250 cents, and sell the remaining three gallons at 15 cents each, for a total of 295 cents of milk profits.

Then, he should rent out the other three cows for 250, 80, and 100 cents, to earn 430 more cents. (He should leave the request for a 40-cent rental unfilled.) This is a total of 725 cents of daily profit.

 

题目链接

 

一道不错的题,和之前的一道USACO的题挺像的 [USACO15DEC]高低卡(洛谷)      BZOJ

最开始我想用dp,但是发现很不好写。然后写了个暴力贪心骗分结果只有20。

不过这道题的确是贪心没错,带技巧的贪心。

首先很容易发现为了使收益最大肯定要把产量高的奶牛留下来产奶,产量低的奶牛租出去奸商思想!

然后我们很容易想到枚举有多少牛要留下来,剩下的肯定就要租出去。

然后我们的n^2思路就完成了,显然是过不去的。然后到这里很多比较年轻的选手就选择了放弃贪心,寻找其他的算法。

然而头铁选手就开始优化贪心了。

其实优化还是很好想的,直接记录两个前缀和就好了。

首先把奶牛的产量从大到小排个序。然后记录下前i个奶牛全留下来的最大收益和后i个奶牛全卖出去的最大收益。

然后O(n)扫一遍取max就好了。记录奶牛留下来时的收益也只需要贪心选最大的就好了。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define p 1000000007
#define LL long long
using namespace std;
inline LL read()
{
    LL sum=0;
    char ch =getchar();
    while(ch<'0'||ch>'9')
        ch=getchar();
    while(ch>='0'&&ch<='9')
    {
        sum=sum*10+ch-'0';
        ch=getchar();
    }
    return sum;
}
int n,m,k;
LL ans=0;
struct cow
{
    LL v,w;
}h[100005];
LL a[100005],pr[100005],sum1[100005],sum2[100005];
bool cmp1(const int &a,const int &b)
{
    return a>b;
}
bool cmp2(const cow &a,const cow &b)
{
    if(a.w==b.w) return a.v>b.v;
    return a.w>b.w;
}
int main()
{
    n=read();m=read();k=read();
    for(register int i=1;i<=n;++i)
        a[i]=read();
    for(register int i=1;i<=m;++i)
    {
        h[i].v=read();
        h[i].w=read();
    }
    for(register int i=1;i<=k;++i)
        pr[i]=read();
    sort(a+1,a+n+1,cmp1);
    sort(pr+1,pr+k+1,cmp1);
    sort(h+1,h+m+1,cmp2);
    for(register int i=1;i<=n;++i)
    {
        if(i<=k)
            sum2[i]=sum2[i-1]+pr[i];
        else 
            sum2[i]=sum2[i-1];
    }
    int mlk=1;
    for(register int i=1;i<=n;++i)
    {
        LL cnt=0;
        while(a[i]>=h[mlk].v&&mlk<=m)
        {
            a[i]-=h[mlk].v;
            cnt+=h[mlk].w*h[mlk].v;
            ++mlk;
        }
        if(mlk<=m)
        {
            cnt+=a[i]*h[mlk].w;
            h[mlk].v-=a[i];
        }
        sum1[i]=sum1[i-1]+cnt;
    }
    for(register int i=1;i<=n;++i)
        ans=max(ans,sum1[i]+sum2[n-i]);
    cout<<ans<<endl;
    return 0;
}

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值