题目描述

小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案。

在蔬菜仓库中,共存放有nn 种蔬菜,小NN 需要根据不同蔬菜的特性,综合考虑各方面因素,设计合理的销售方案,以获得最多的收益。

在计算销售蔬菜的收益时,每销售一个单位第ii 种蔬菜,就可以获得a_iai​ 的收益。

特别地,由于政策鼓励商家进行多样化销售,第一次销售第 i 种蔬菜时,还会额外得到s_isi​ 的额外收益。

在经营开始时,第ii 种蔬菜的库存为c_ici​ 个单位。

然而,蔬菜的保鲜时间非常有限,一旦变质就不能进行销售,不过聪明的小 N 已经计算出了每个单位蔬菜变质的时间:对于第ii 种蔬菜,存在保鲜值x_ixi​ ,每天结束时会有x_ixi​ 个单位的蔬菜变质,直到所有蔬菜都变质。(注意:每一单位蔬菜的变质时间是固定的,不随销售发生变化)

形式化地:对于所有的满足条件d \times x_i \leqslant cid×xi​⩽ci 的正整数dd ,有x_ixi​ 个单位的蔬菜将在第dd 天结束时变质。

特别地,若(d - 1) \times x_i \leqslant c_i \leqslant d \times x_i(d−1)×xi​⩽ci​⩽d×xi​ ,则有c_i - (d - 1) \times x_ici​−(d−1)×xi​ 单位的蔬菜将在第dd 天结束时变质。

注意,当x_i = 0xi​=0 时,意味着这种蔬菜不会变质。

同时,每天销售的蔬菜总量也是有限的,最多不能超过mm 个单位。

现在,小 N 有kk 个问题,想请你帮忙算一算。每个问题的形式都是:对于已知的p_jpj​ ,如果需要销售p_jpj​ 天,最多能获得多少收益?

输入输出格式

输入格式:

第一行包含三个正整数n, m, kn,m,k ,分别表示蔬菜的种类数目、每天能售出蔬菜总量上限、小 N 提出的问题的个数。

接下来nn 行,每行输入四个非负整数,描述一种蔬菜的特点,依次为a_i, s_i, c_i, x_iai​,si​,ci​,xi​ ,意义如上文所述。

接下来kk 行,每行输入一个非负整数p_jpj​ ,意义如上文所述。

输出格式:

输出kk 行,每行包含一个整数,第ii 行的数表示第ii 个问题的答案。

题意:

     定义了一种蔬菜为:ai,si,ci,xi;

     意思是蔬菜的价格为ai,第一份卖出时价格为ai+si,一共有ci份,每天会有xi份过期;每天最多卖出m份蔬菜,多组输入天数依次最大化收入;

题解:

     ①一个很神的贪心:我们尽量晚点卖过期晚的,早点卖贵的;

     ②现在想象有一个天数的序列,我们狡猾而又贪心地往里面填蔬菜。为了处理第一次卖出,我们把一种蔬菜分成两种,(1,ai+si)和(ci-1,ai),第一份蔬菜最后过期。把所有蔬菜里最贵的先拿出来,找到当前蔬菜最后过期的那一天,尽量把那一天放满,满了之后再往前面找,后面过期的在前一天一定可以放,动态加上比较早过期的一直放直到放不下或放完。

     ③本来能放的最后一天(可以(ci-1)/xi+1)o(1)算,并查集维护一下往前没满的第一个位置可以保证复杂度。注意特判一下 xi==0永不过期;

     ⑤要求多组询问,考虑d天内卖掉的蔬菜为S,我们d-1天一定是丢掉比较便宜的蔬菜,丢掉的个数即为d天选的蔬菜减前面空着的总份数,求出最后一天的状态往前减即可。

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N = ;
int n,m,k,f[N],d[N],ga[N],g[N],cnt,tot,Q[N],maxd,upd[N];
ll ans[N],sum,L[N],R;
struct node {int c,a,x,d;}A[N];
char gc(){
static char *p1,*p2,s[];
if(p1==p2) p2=(p1=s)+fread(s,,,stdin);
return (p1==p2)?EOF:*p1++;
}
int rd(){
int x = ; char c = gc();
while(c<''||c>'') c = gc();
while(c>=''&&c<='') x = x * + c - '',c = gc();
return x;
}
bool cmp(const node &x,const node &y){return x.a > y.a;}
int find(int x){return(f[x]==x)?x:f[x]=find(f[x]);}
void Union(int x,int y){int fx = find(x),fy = find(y);if(fx==fy)return;f[fy] = fx;}
void calc(int idx,int c,int a){
sum += 1ll * c * a;
g[cnt] += c,ga[cnt] = a;
d[idx] += c;
if(d[idx]==m) Union(idx-,idx);
}
int main()
{ //freopen("mzoj1115.in","r",stdin);
//freopen("mzoj1115.out","w",stdout);
freopen("testdata.in","r",stdin);
freopen("testdata.out","w",stdout);
n = rd(); m = rd(); k = rd();
for(int i = ,a,s,c,x;i <= n;i++){
a=rd(),s=rd(),c=rd(),x=rd();
A[++tot] = (node){,a+s,,x?(c-)/x+:N};
if(--c) A[++tot] = (node){c,a,x,x?(c-)/x+:N};
}
for(int i = ,x;i <= k;i++) {
maxd = max(maxd,Q[i] = rd());
}
sort(A+,A+tot+,cmp);
for(int i = ;i <= maxd;i++) f[i] = i;
for(int i = ;i <= tot;i++) {
cnt++;
int idx=find(min(A[i].d,maxd));
int res = (idx-)*A[i].x,now = A[i].c - res;
while(idx&&now){
int tmp = m - d[idx];
int mn = min(tmp,now);
calc(idx,mn,A[i].a);
now -= mn;
int p = idx; idx = find(idx - ); p-=idx;
if(res) now += p*A[i].x,res -= p*A[i].x;
}
if(!find(maxd)) break;
}
//for(int i = 1;i <= cnt/2;i++) swap(g[i],g[cnt-i+1]),swap(ga[i],ga[cnt-i+1]);
for(int i = ;i <= maxd;i++) L[i] = m - d[i] + L[i - ];
for(int i = maxd;i >= ;i--)
upd[i] = max(R - L[i],0ll),R+=d[i];
for(int i = maxd;i>=;i--){
ans[i] = sum;
int tmp = upd[i-] - upd[i];
while(tmp){
int mn = min(tmp,g[cnt]);
sum -= 1ll * ga[cnt] * mn;
tmp -= mn; g[cnt] -= mn; if(!g[cnt]) cnt--;
}
}
for(int i = ;i <= k;i++) printf("%lld\n",ans[Q[i]]);
return ;
}//by tkys_Austin;

bzoj4946 Noi2017 蔬菜的更多相关文章

  1. bzoj4946: [Noi2017]蔬菜 神烦贪心

    题目链接 bzoj4946: [Noi2017]蔬菜 题解 挺神的贪心 把第次买的蔬菜拆出来,记下每种蔬菜到期的日期,填第一单位蔬菜比其他的要晚 按价格排序后,贪心的往前面可以填的位置填就可以了.找可 ...

  2. BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流

    题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...

  3. BZOJ4946 NOI2017蔬菜(贪心+堆)

    容易想到一个费用流做法:将每种蔬菜拆成p种,对应p个过期时间,每一种向可以卖的时间连边,第一次卖的奖励算在最晚过期的一种里.对于天数动态加点.不过这样边数太多了,因为第i天能卖的第i-1天一定能卖,可 ...

  4. 【BZOJ4946】[NOI2017]蔬菜(贪心)

    [BZOJ4946][NOI2017]蔬菜(贪心) 题面 BZOJ 洛谷 UOJ 题解 忽然发现今年\(NOI\)之前的时候切往年\(NOI\)的题目,就\(2017\)年的根本不知道怎么下手(一定是 ...

  5. [NOI2017]蔬菜

    [NOI2017]蔬菜 题目描述 大意就是有\(n\)种物品,第\(i\)个物品有\(c_i\)个,单价是\(a_i\).然后每天你可以卖出最多\(m\)个物品.每天结束后第\(i\)种物品会减少\( ...

  6. 4946: [Noi2017]蔬菜

    4946: [Noi2017]蔬菜 http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf 分析: 贪心. 首先可以将一个蔬菜拆成两个,一个是有加成 ...

  7. [NOI2017]蔬菜 贪心

    题面: [NOI2017]蔬菜 题解: 首先每天蔬菜会变质这点并不好处理,我们考虑让时间倒流,从后向前处理,这样的话就相当于每天都会得到一定量的蔬菜. 这样做有什么好处呢? 我们可以发现一个性质:如果 ...

  8. BZOJ4946 & 洛谷3826 & UOJ318:[NOI2017]蔬菜——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4946 https://www.luogu.org/problemnew/show/P3826 ht ...

  9. NOI2017蔬菜(贪心)

    小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案. 在蔬菜仓库中,共存放有 n 种蔬菜,小 N 需要根据不同蔬菜的特性,综合考虑各 方面因素,设计合理的销售方案,以获得最多的收益. 在计算销售蔬菜的 ...

随机推荐

  1. aws中的路由表

    参考官方文档: 由表中包含一系列被称为路由的规则,可用于判断网络流量的导向目的地. 在您的 VPC 中的每个子网必须与一个路由表关联:路由表控制子网的路由.一个子网一次只能与一个路由表关联,但您可以将 ...

  2. Scala 对象

    1. 单例对象 对于任何你在Java中会使用单例对象的地方, 在scala中都可以使用对象来实现; scala字段没有静态方法或者静态字段, 可以使用object语法结构达到同样的效果,对象(obje ...

  3. nyoj n-1位数

    n-1位数 时间限制:3000 ms  |  内存限制:65535 KB 难度:1   描述 已知w是一个大于10但不大于1000000的无符号整数,若w是n(n≥2)位的整数,则求出w的后n-1位的 ...

  4. Ajax 的onreadystatechange事件注意事项.

    <script type="text/javascript"> function createXHR() { var request = false; try { re ...

  5. LeetCode & Q283-Move Zeroes-Easy

    Array Two Pointers Description: Given an array nums, write a function to move all 0's to the end of ...

  6. Python内置函数(33)——any

    英文文档: any(iterable) Return True if any element of the iterable is true. If the iterable is empty, re ...

  7. Spring知识点回顾(03)Bean的 Scope

    sigleton prototype request session globalsession stepscope

  8. virtualbox中linux系统与windows实现共享文件夹

    最近有一次,需要在linux获取在我windows系统里的安装包,但是呢不论如何也拿不过去. virtualbox虽然提供了双向拖放,但是实在是太不健壮了,感觉基本就没好使过. 于是我想到了用共享文件 ...

  9. 集合之深入理解HashMap

    Hashmap是一种非常常用的.应用广泛的数据类型 1.hashmap的数据结构 要知道hashmap是什么,首先要搞清楚它的数据结构,在java编程语言中,最基本的结构就是两种,一个是数组,另外一个 ...

  10. python基础二(基础数据类型)

    一. 引子 1. 什么是数据 x=10,10是我们要存储的数据 2. 为何数据要分不同的类型 数据是用来表示状态的,不同的状态就应该用不同的类型的数据去表示 3.数据类型 数字 字符串 列表 元组 字 ...