题目链接

题解:

貌似一眼看过去是一个贪心。

其他的算法要记录的东西就太多了。

部分分其实很高。但是没有什么提示。

想一些套路:二分?不行还要贪心判断。

分治?前后取法是有影响的。

时光倒流?

也许可以?

其实比较麻烦的是蔬菜变质。这样就使得我们不能每次卖最贵的。

如果时光倒流,那么就会有些蔬菜在某一个时刻以某一个初值出现,然后每过一天,增长固定的个数。

那么,面对最后一天,我们就剩下这么多的菜了。肯定要卖最贵的m个

然后,倒数第二天,一些蔬菜出现了,一些蔬菜变多了,我们在最后一天卖菜的基础上,可以继续选择最贵的m个。

因为,最后一天的菜和倒数第二天的菜交换一定不优,因为可能倒数第二天能买到的,最后一天就坏了。而由于取最大的m个,某天卖其他的菜也不会更优。

类似数学归纳法可以证明。

现在我们可以找出来p天的最大收益了。

但是,询问太多了, 可以不可以递推呢?

可以。

求出max(pi)的值mxans

然后,每往前提一天,那么,就把所有卖过的菜中,删掉最便宜的m个。

合法显然,因为后面能卖的,前面一定能卖、

如果不卖这些,同层之间交换不优的。

离线处理,然后倒序递推即可。

细节比较多:

1.不能除以0

2.等等

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize"Ofast"
#include<bits/stdc++.h>
#define ri register int
using namespace std;
#define int long long
#define numb (ch^'0')
typedef long long ll;
const int N=2e5+;
void rd(int &x){
char ch;x=;
while(!isdigit(ch=getchar()));
for(x=numb;isdigit(ch=getchar());x=(x<<)+(x<<)+numb);
}
struct node{
ll val;
int id;
int sold;
bool friend operator <(node a,node b){
return a.val<b.val;
}
}sta[N];
int top;
ll mxans;
int val[N],c[N],s[N],dele[N];
int sell[N];
int app[N],rem[N];
priority_queue<node>q1;
struct bac{
ll val;
ll sum;
bool friend operator <(bac a,bac b){
return a.val>b.val;
}
};
priority_queue<bac>q2;
int n,m,k;
struct question{
int day;
int id;
bool friend operator<(question a,question b){
return a.day>b.day;
}
}que[N];
ll ans[N];
int up;
int id[N];
vector<int>mem[N];//appear day
bool cmp(int a,int b){
return val[a]>val[b];
}
signed main(){
rd(n);rd(m);rd(k);
bool fl=true;
for(ri i=;i<=n;i++){
rd(val[i]),rd(s[i]),rd(c[i]),rd(dele[i]);
if(dele[i]) fl=false;
}
for(int i=;i<=k;i++){
rd(que[i].day);
//scanf("%d",&que[i].day);
que[i].id=i;
}sort(que+,que+k+);
up=que[].day;
//cout<<que[k-1].day<<endl;
//cout<<" up "<<up<<endl;
for(ri i=;i<=n;i++){
if(dele[i]==){
app[i+n]=up;
rem[i+n]=;
dele[i+n]=;
c[i+n]=;
val[i+n]=s[i]+val[i];
mem[app[i+n]].push_back(i+n); c[i]--;
if(c[i]==) continue;//warning!!
int exi=up;
int re=c[i];
app[i]=exi,rem[i]=re;
mem[exi].push_back(i);
continue;
}
app[i+n]=(c[i]+dele[i]-)/dele[i];
if(app[i+n]>up) app[i+n]=up;
rem[i+n]=;
dele[i+n]=;
c[i+n]=;
val[i+n]=s[i]+val[i];
mem[app[i+n]].push_back(i+n); c[i]--;
if(c[i]==) continue;//warning!!
int exi=(c[i]+dele[i]-)/dele[i];
int re=c[i]%dele[i];
if(re==) re=dele[i];
if(exi>up){
re+=(exi-up)*dele[i];
exi=up;
}
app[i]=exi,rem[i]=re;
mem[exi].push_back(i);
}
//for(int i=1;i<=2*n;i++){
/// cout<<i<<" : "<<val[i]<<" "<<c[i]<<" "<<app[i]<<" "<<rem[i]<<endl;
//}
if(fl){
for(int i=;i<=*n;i++) {
id[i]=i;
}
sort(id+,id+*n+,cmp);
int ptr=k;
if(que[ptr].day==) ptr--;
int r=;
//cout<<" day "<<que[ptr].day<<endl;
for(int d=;d<=up;d++){
int now=id[r];
//cout<<d<<" : "<<r<<" : "<<c[now]<<endl;
int nd=m;
while(r<=*n&&c[id[r]]<nd){
int now=id[r];
nd-=c[now];
mxans+=val[now]*c[now];
r++;
}
//cout<<" nd "<<nd<<" "<<r<<endl;
if(r<=*n){
int now=id[r];
c[now]-=nd;
mxans+=val[now]*nd;
}
while(que[ptr].day==d&&ptr){
//cout<<que[ptr].id<<endl;
ans[que[ptr].id]=mxans;ptr--;
}
//cout<<ptr<<endl;
}
//cout<<r<<" "<<mxans<<endl;
for(int i=;i<=k;i++){
printf("%lld\n",ans[i]);
}
return ;
}
for(ri i=up;i>=;i--){
for(ri j=;j<mem[i].size();j++){
int id=mem[i][j];
node tmp;tmp.val=(ll)val[id];tmp.id=id;tmp.sold=;
q1.push(tmp);
}
int nd=m;
while(nd){
if(q1.empty()) break;
node now=q1.top();q1.pop();
int has=(app[now.id]-i)*dele[now.id]+rem[now.id]-now.sold;
//cout<<" has "<<now.id<<" : "<<has<<endl;
if(has>nd){
now.sold+=nd;
mxans+=val[now.id]*nd;
sell[now.id]+=nd;
nd=;
}
else{
now.sold+=has;
mxans+=val[now.id]*has;
sell[now.id]+=has;
nd-=has;
}
if(now.id<=n) sta[++top]=now;//warning!! id>n not push back
}
while(top){
q1.push(sta[top]);top--;
}
//cout<<" after "<<i<<" : "<<mxans<<endl;
}
ans[que[].id]=mxans;
if(k==){
printf("%lld",mxans);
return ;
}
int tot=;
for(ri i=;i<=*n;i++){
if(sell[i]){
tot+=sell[i];
bac tmp;
tmp.sum=sell[i];
tmp.val=(ll)val[i];
q2.push(tmp);
}
}
int ptr=;
for(ri i=up;i>=;i--){
while(ptr<=k&&que[ptr].day==i){
ans[que[ptr].id]=mxans;ptr++;
}
if((i-)*m>=tot) continue;//warning!!!
if(i==) break;
int nd=min(m,tot-((i-)*m));
while(nd){
if(q2.empty()) break;
bac now=q2.top();q2.pop();
if(now.sum>nd){
now.sum-=nd;
mxans-=nd*now.val;
nd=;
q2.push(now);
}
else{
mxans-=now.sum*now.val;
nd-=now.sum;
}
}
}
for(int i=;i<=k;i++){
printf("%lld\n",ans[i]);
}
return ;
} /*
Author: *Miracle*
Date: 2018/10/14 14:19:49
*/

[NOI2017]蔬菜——时光倒流+贪心的更多相关文章

  1. NOI2017蔬菜(贪心)

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

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

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

  3. [NOI2017]蔬菜 贪心

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

  4. [NOI2017]蔬菜(贪心+递推)

    这题很有思维难度,乍一看基本无从下手. 给每个蔬菜钦定退役的时间显然很困难,可以考虑让时光倒流,从后向前递推,然后就变成了某个时间点有一部分蔬菜服役,而已经服役的蔬菜不会退役了.然后就可以直接考虑贪心 ...

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

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

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

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

  7. [NOI2017]蔬菜

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

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

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

  9. 4946: [Noi2017]蔬菜

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

随机推荐

  1. 《Spark 官方文档》在Mesos上运行Spark

    本文转自:http://ifeve.com/spark-mesos-spark/ 在Mesos上运行Spark Spark可以在由Apache Mesos 管理的硬件集群中运行. 在Mesos集群中使 ...

  2. @meida 媒体查询

    示例 @meida 媒体查询 在进行书写的时候需要考虑到加载顺序和样式权重使用meida响应式实现不同宽度布局示例 常用工具 https://mydevice.io 参考链接 https://deve ...

  3. Linux系统负载查询

    查询Linux系统负载情况,一般需要了解三个方面的信息: 1.Linux系统配置.如Linux版本号.CPU.内存.网络.磁盘等: 2.收集系统负载信息的手段.常用的工具包有sysstat和procp ...

  4. Bitcoin: A Peer-to-Peer Electronic Cash System

    Bitcoin: A Peer-to-Peer Electronic Cash System Satoshi Nakamoto October 31, 2008 Abstract A purely p ...

  5. 基于Kubernetes(k8s)网络方案演进

    VIP PaaS在接近两年时间里,基于kubernetes主要经历四次网络方案的变迁: 1. kubernetes + flannel 2. 基于Docker libnetwork的网络定制 3. k ...

  6. ThinkPHP - 2 - SAE(新浪云)部署

    ThinkPHP3.2核心内置了对SAE平台的支持(采用了应用模式的方式),具有自己的独创特性,能够最大程度的使用ThinkPHP的标准特性,让开发人员感受不到SAE和普通环境的差别.甚至可以不学习任 ...

  7. JavaScript筑基篇(二)->JavaScript数据类型

    说明 介绍JavaScript数据类型 目录 前言 参考来源 前置技术要求 JavaScript的6种数据类型 哪6种数据类型 undefined 类型 null 类型 boolean 类型 numb ...

  8. canvas学习(三):文字渲染

    一.绘制基本的文字: var canvas = document.getElementById("myCanvas") var ctx = canvas.getContext('2 ...

  9. js随机数算法

    function rnd( seed ){ seed = ( seed * 9301 + 49297 ) % 233280; //为何使用这三个数? return seed / ( 233280.0 ...

  10. Calculator 2

    github地址:https://github.com/YooRarely/object-oriented.git 新增: 计算类(拥有计算功能) 采用符号优先级计算方法 对符号不匹配的如 -2 ,自 ...