luogu4181 [USACO18JAN]Rental Service

http://www.elijahqi.win/2018/02/02/luogu4181-usaco18janrental-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
NN

N cows (
1≤N≤100,0001 \leq N \leq 100,000

1≤N≤100,000 ), each capable of producing some amount of milk every day. The
MM

M stores near FJ’s farm (
1≤M≤100,0001 \leq M \leq 100,000

1≤M≤100,000 ) each offer to buy a certain amount of milk at a certain price. Moreover, Farmer John’s
RR

R (
1≤R≤100,0001 \leq R \leq 100,000

1≤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
NN

N ,
MM

M , and
RR

R . The next
NN

N lines each contain an integer
cic_i

ci​ (
1≤ci≤1,000,0001 \leq c_i \leq 1,000,000

1≤ci​≤1,000,000 ), indicating that Farmer John’s
ii

i th cow can produce
cic_i

ci​ gallons of milk every day. The next
MM

M lines each contain two integers
qiq_i

qi​ and
pip_i

pi​ (
1≤qi,pi≤1,000,0001 \leq q_i, p_i \leq 1,000,000

1≤qi​,pi​≤1,000,000 ), indicating that the
ii

i th store is willing to buy up to
qiq_i

qi​ gallons of milk for
pip_i

pi​ cents per gallon. Keep in mind that Farmer John can sell any amount of milk between zero and
qiq_i

qi​ gallons to a given store. The next
RR

R lines each contain an integer
rir_i

ri​ (
1≤ri≤1,000,0001 \leq r_i \leq 1,000,000

1≤ri​≤1,000,000 ), indicating that one of Farmer John’s neighbors wants to rent a cow for
rir_i

ri​ 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.

填坑ing zhx巨佬很早之前A过的题 经过了thuwc的被血虐 今天一直自己想题所以做题速度放慢了很多 此题有两种模式 1、可以卖牛奶2、可以出租奶牛 根据直觉可以感觉到 我出租奶牛一定得是出租

那些产奶量偏少的 然后靠产奶为收入的那么一定得是 产奶量多的奶牛 那么就针对两部分分别计算 如果i头奶牛全产奶 我最多获得的经济收益是多少然后再枚举一下我i头奶牛全出租获得的收益是多少 那么这时候再枚举一下 我几头奶牛出租几头奶牛产奶 选最大即可

#include<cstdio>
#include<algorithm>
#define ll long long
#define N 110000
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=gc();}
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
    return x*f;
}
struct node{
    int nd,pri;
}s[N];
int n,m,r,milk[N],price[N];ll sum[N],sum1[N];
inline bool cmp1(const int &a,const int &b){return a>b;}
inline bool cmp(const node &a,const node &b){return a.pri>b.pri;}
int main(){
    freopen("rental.in","r",stdin);
    freopen("rental.out","w",stdout);
    n=read();m=read();r=read();
    for (int i=1;i<=n;++i) milk[i]=read();sort(milk+1,milk+n+1,cmp1);
    for (int i=1;i<=m;++i) s[i].nd=read(),s[i].pri=read();
    sort(s+1,s+m+1,cmp);int now=1,now1=1;
    for (int i=1;i<=r;++i) price[i]=read();sort(price+1,price+r+1,cmp1);ll ans=0;
    for (int i=1;i<=r;++i) sum[i]=sum[i-1]+price[i];
    for (int i=1;i<=n;++i){
        ll tmp1=0;int c=milk[i],pre=now;node e=s[now];
        while(c>=s[now].nd&&now<=m){
            tmp1+=(ll)s[now].nd*s[now].pri;
            c-=s[now].nd;++now;e=s[now];
        }tmp1+=(ll)c*s[now].pri;e.nd-=c;
        sum1[i]=sum1[i-1]+tmp1;s[now]=e;
    }
    for (int i=1;i<=n;++i) ans=max(ans,sum1[i]+sum[n-i]);
    printf("%lld\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一道经典的单调栈问题。题目描述如下: 有 $n$ 个湖,第 $i$ 个湖有一个高度 $h_i$。现在要在这些湖之间挖一些沟渠,使得相邻的湖之间的高度差不超过 $d$。请问最少需要挖多少个沟渠。 这是一道单调栈的典型应用题。我们可以从左到右遍历湖的高度,同时使用一个单调栈来维护之前所有湖的高度。具体来说,我们维护一个单调递增的栈,栈中存储的是湖的下标。假设当前遍历到第 $i$ 个湖,我们需要在之前的湖中找到一个高度最接近 $h_i$ 且高度不超过 $h_i-d$ 的湖,然后从这个湖到第 $i$ 个湖之间挖一条沟渠。具体的实现可以参考下面的代码: ```c++ #include <cstdio> #include <stack> using namespace std; const int N = 100010; int n, d; int h[N]; stack<int> stk; int main() { scanf("%d%d", &n, &d); for (int i = 1; i <= n; i++) scanf("%d", &h[i]); int ans = 0; for (int i = 1; i <= n; i++) { while (!stk.empty() && h[stk.top()] <= h[i] - d) stk.pop(); if (!stk.empty()) ans++; stk.push(i); } printf("%d\n", ans); return 0; } ``` 这里的关键在于,当我们遍历到第 $i$ 个湖时,所有比 $h_i-d$ 小的湖都可以被舍弃,因为它们不可能成为第 $i$ 个湖的前驱。因此,我们可以不断地从栈顶弹出比 $h_i-d$ 小的湖,直到栈顶的湖高度大于 $h_i-d$,然后将 $i$ 入栈。这样,栈中存储的就是当前 $h_i$ 左边所有高度不超过 $h_i-d$ 的湖,栈顶元素就是最靠近 $h_i$ 且高度不超过 $h_i-d$ 的湖。如果栈不为空,说明找到了一个前驱湖,答案加一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值