[NOI2017]蔬菜

题目描述

大意就是有\(n\)种物品,第\(i\)个物品有\(c_i\)个,单价是\(a_i\)。然后每天你可以卖出最多\(m\)个物品。每天结束后第\(i\)种物品会减少\(x_i\)个。第一次出售\(i\)物品时还会额外获得\(s_i\)的收益。

每次询问给出\(p\),问\(p\)天能得到的最大收益。

\(1\leq n,p\leq 10^5,1\leq m\leq 10,1\leq a_i,c_i\leq 10^9\)。

神仙题啊!不会网络流,不会贪心,直接自闭。

Orz

60分的网络流做法

因为很容易发现这个题状态太大,无法\(DP\),所以我们考虑费用流之类的东西。然后我们发现这个题每个物品的上限时刻在变化,很难建图。

对于这种流量变化的费用流我们考虑拆点。我们将每种蔬菜拆成\(P\)个点,第\(i\)个点到汇点的流量就是第\(i\)天比第\(i+1\)天多的数量。我们还应该额外拆一个点表示第一次出售。然后第\(i\)个点向第\(i+1\)个点连边。

我们增广\(P\)次,就得到了\(1\)到\(P\)的答案。

100分的贪心算法

我们发现每天有蔬菜减少非常不好做,于是我们考虑倒着做。这样相当于每天我们会得到一些蔬菜。所以我们就可以每次选收益最大的蔬菜来卖。

具体实现有点复杂。先开一个堆。记录每种蔬菜最晚在什么时候出现。当倒推到第\(i\)天时,将在最晚在当天出现的蔬菜丢进堆里。每次取堆顶的蔬菜来卖。

这样我们就得到了\(P\)天的答案。

然后考虑递推出\(1\)到\(P-1\)的答案。相当于说我们要把卖出的蔬菜删除掉。一个比较显然的结论就是我们尽量在天数偏小的时候删除(因为我们卖蔬菜肯定也是越早卖越好)。删除的时候就一直删除当前价值最小的。

不用考虑会不会删除操作时出现了不合法的情况。因为我们发现删除的时间是没有影响的。可以这么感性理解分析:假设我们递推到第\(i\)天,要删除一些第\(k\)种蔬菜,那么我们就将相应的卖出操作撤销,在它之后的卖出操作全部提前,这肯定也是合法的。

据说这就是模拟费用流。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 100005 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} int n,m,k;
ll ans;
int a[N],s[N],c[N],x[N];
struct node {
ll id,val;
node() {val=id=0;}
node(int i,int v) {val=v,id=i;}
bool operator <(const node &a)const {return val<a.val;}
};
priority_queue<node>q;
const int P=100000;
int sold;
vector<int>ap[N];
vector<int>tem;
int used[N];
ll Ans[N];
int main() {
n=Get(),m=Get(),k=Get();
for(int i=1;i<=n;i++) {
a[i]=Get(),s[i]=Get(),c[i]=Get(),x[i]=Get();
if(!x[i]) ap[P].push_back(i);
else ap[min(P,(c[i]+x[i]-1)/x[i])].push_back(i);
} for(int i=P;i>=1;i--) {
for(int j=0;j<ap[i].size();j++) {
q.push(node(ap[i][j],s[ap[i][j]]+a[ap[i][j]]));
}
tem.clear();
int res=m;
while(res) {
if(!q.size()) break;
int id=q.top().id,val=q.top().val;
q.pop();
if(!used[id]) {
res--;
used[id]=1;
ans+=val;
q.push(node(id,a[id]));
} else {
int now=min(res,c[id]-used[id]-(i-1)*x[id]);
res-=now;
used[id]+=now;
ans+=1ll*now*val;
if(used[id]<c[id]) tem.push_back(id);
}
}
sold+=m-res;
for(int j=0;j<tem.size();j++) q.push(node(tem[j],a[tem[j]]));
} while(q.size()) q.pop();
for(int i=1;i<=n;i++) {
if(used[i]==1) q.push(node(i,-s[i]-a[i]));
else if(used[i]>1) q.push(node(i,-a[i]));
} Ans[P]=ans;
for(int i=P;i>1;i--) {
tem.clear();
int res=max(0,sold-(i-1)*m);
while(res) {
if(!q.size()) break;
int id=q.top().id,val=q.top().val;
q.pop();
if(used[id]==1) {
sold--;
used[id]--;
res--;
ans+=val;
} else {
int now=min(res,used[id]-1);
used[id]-=now;
res-=now;
ans+=1ll*now*val;
sold-=now;
if(used[id]==1) q.push(node(id,-s[id]-a[id]));
else q.push(node(id,-a[id]));
}
}
Ans[i-1]=ans;
}
while(k--) {
int x=Get();
cout<<Ans[x]<<"\n";
}
return 0;
}

[NOI2017]蔬菜的更多相关文章

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

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

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

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

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

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

  4. 4946: [Noi2017]蔬菜

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

  5. [NOI2017]蔬菜 贪心

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

  6. bzoj4946 Noi2017 蔬菜

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

  7. NOI2017蔬菜(贪心)

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

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

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

  9. [NOI2017]蔬菜(贪心)

    神仙题啊! 早上开了两个多小时,终于肝出来了,真香 我们考虑从第 \(10^5\) 天开始递推,先生成 \(p=10^5\) 的解,然后逐步推出 \(p-1,...,2,1\) 的解. 那怎么推出 \ ...

随机推荐

  1. mysql的coalesce使用技巧

    今天无意间发现mysql的coalesce, coalesce()解释:返回参数中的第一个非空表达式(从左向右依次类推): 使用示例:a,b,c三个变量. ,); // Return 2 select ...

  2. js 点击文本框,预览选择图片

    点击文件选择框,选择图片文件,通过FileReader对象,读取图片文件中的内容,存放于result中,具体代码如下 <input type="file" onchange= ...

  3. 使用JSDoc自动生成代码文档

    译者按: 代码要有规范的注释,遵从jsDoc规则来注释可以生成有用的文档. 原文: Generate docs and host it with JSDoc and GitHub Pages 译者:  ...

  4. 解决PHP Redis扩展无法加载的问题(zend_new_interned_string in Unknown on line 0)

    出错代码如下 PHP Warning: PHP Startup: Unable to load 最近在工作中需要使用PHP访问Redis,从https://github.com/phpredis/ph ...

  5. mac svn的使用

    一.概述 在windows下,我们常常用TortoiseSVN管理svn代码.在mac下,自带svn客户端和服务器端功能. 二.服务端:创建代码仓库,用来存储客户端所上传的代码 (1)创建svn代码存 ...

  6. K8S 通过 yaml 文件创建资源

    创建 pod cd ~ vi pod-demo.yaml # 内容如下 apiVersion: v1 kind: Pod metadata: name: pod-demo namespace: def ...

  7. 李飞飞确认将离职!谷歌云AI总帅换人,卡耐基·梅隆老教授接棒

    https://mp.weixin.qq.com/s/i1uwZALu1BcOq0jAMvPdBw 看点:李飞飞正式回归斯坦福,新任谷歌云AI总帅还是个教授,不过这次是全职. 智东西9月11日凌晨消息 ...

  8. loadrunner 脚本优化-事务时间简介

    脚本优化-事务时间简介 by:授客 QQ:1033553122 事务概念 事务是指用户在客户端做一种或多种业务所需要的操作集(actions),通过事务开始和结束函数可以标记完成该业务所需要的操作内容 ...

  9. Android项目实战(四十三):夜神模拟器

    一.下载模拟器到电脑 夜神模拟器 二.环境配置 计算机--系统--高级系统设置--环境变量 PATH 里面加入夜神模拟器的安装目录下的bin文件 三.启动模拟器 四.运行cmd命令,cd到夜神安装目录 ...

  10. C#:如何使方法过时,如何否决方法

    在使用.Net Frameworkd进行开发时,经常可以在方法的智能提示ToolTip上面看到一个方法是[否决的],如图: 或者在警告里面: 甚至使用[否决的]方法的时候还会造成编译错误: 上面的这些 ...