题目链接

题解:

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

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

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

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

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

时光倒流?

也许可以?

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

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

那么,面对最后一天,我们就剩下这么多的菜了。肯定要卖最贵的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. Linux命令应用大词典-第35章 终端

    35.1 tty:显示当前连接到当前标准输入的终端设备文件名 35.2 consoletype:显示连接到标准输入的控制台类型 35.3 fgconsole:显示活动的虚拟终端数量 35.4 ming ...

  2. eclipse格式化

    一.eclipse格式化的必要性 1.便于阅读 2.便于协作 二.eclipse格式化快捷键 ctrl shift + F

  3. 1. 两数之和【Leetcode中国,by java】

    给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...

  4. git branch 分支与合并

    在使用 git 进行分支开发与合并的时候需要用到这些命令.其他基本 git 命令参考 Git 简易食用指南 git branch 查看分支 git branch 查看当前分支情况 创建分支 git b ...

  5. 十面阿里,七面头条,六个Offer,春招结束

    作者:jkgeekjack链接:https://www.nowcoder.com/discuss/80156?type=0&order=0&pos=13&page=2来源:牛客 ...

  6. POJ 2187 Beauty Contest(凸包+旋转卡壳)

    Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, ea ...

  7. HDU 2491 Priest John's Busiest Day(贪心)(2008 Asia Regional Beijing)

    Description John is the only priest in his town. October 26th is the John's busiest day in a year be ...

  8. iOS开发实现UIView随着子控件的高度的变化而变化

    例子 其实看完上面的叙述,你会思考,到底什么情况下,一个UIView需要只设置坐标不设置大小呢?其实这种场景相当普遍.比如,我们常常会碰到,一个View中有两个Label,两个Label的高度均和内容 ...

  9. 安装配置erlang_db_driver

    erlang-db-driver是北京融易通公司开源的一个erlang支持众多数据库的一个驱动类库,据其wiki介绍,其支持MySQL, Oracle, Sybase, DB2 and Informi ...

  10. sublime Text3 如何自动排版代码

    安装 html beautiful 然后按ctrl+shift+alt+f