[NOI2017]蔬菜——时光倒流+贪心
题解:
貌似一眼看过去是一个贪心。
其他的算法要记录的东西就太多了。
部分分其实很高。但是没有什么提示。
想一些套路:二分?不行还要贪心判断。
分治?前后取法是有影响的。
时光倒流?
也许可以?
其实比较麻烦的是蔬菜变质。这样就使得我们不能每次卖最贵的。
如果时光倒流,那么就会有些蔬菜在某一个时刻以某一个初值出现,然后每过一天,增长固定的个数。
那么,面对最后一天,我们就剩下这么多的菜了。肯定要卖最贵的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]蔬菜——时光倒流+贪心的更多相关文章
- NOI2017蔬菜(贪心)
小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案. 在蔬菜仓库中,共存放有 n 种蔬菜,小 N 需要根据不同蔬菜的特性,综合考虑各 方面因素,设计合理的销售方案,以获得最多的收益. 在计算销售蔬菜的 ...
- BZOJ4946 NOI2017蔬菜(贪心+堆)
容易想到一个费用流做法:将每种蔬菜拆成p种,对应p个过期时间,每一种向可以卖的时间连边,第一次卖的奖励算在最晚过期的一种里.对于天数动态加点.不过这样边数太多了,因为第i天能卖的第i-1天一定能卖,可 ...
- [NOI2017]蔬菜 贪心
题面: [NOI2017]蔬菜 题解: 首先每天蔬菜会变质这点并不好处理,我们考虑让时间倒流,从后向前处理,这样的话就相当于每天都会得到一定量的蔬菜. 这样做有什么好处呢? 我们可以发现一个性质:如果 ...
- [NOI2017]蔬菜(贪心+递推)
这题很有思维难度,乍一看基本无从下手. 给每个蔬菜钦定退役的时间显然很困难,可以考虑让时光倒流,从后向前递推,然后就变成了某个时间点有一部分蔬菜服役,而已经服役的蔬菜不会退役了.然后就可以直接考虑贪心 ...
- 【BZOJ4946】[NOI2017]蔬菜(贪心)
[BZOJ4946][NOI2017]蔬菜(贪心) 题面 BZOJ 洛谷 UOJ 题解 忽然发现今年\(NOI\)之前的时候切往年\(NOI\)的题目,就\(2017\)年的根本不知道怎么下手(一定是 ...
- bzoj4946: [Noi2017]蔬菜 神烦贪心
题目链接 bzoj4946: [Noi2017]蔬菜 题解 挺神的贪心 把第次买的蔬菜拆出来,记下每种蔬菜到期的日期,填第一单位蔬菜比其他的要晚 按价格排序后,贪心的往前面可以填的位置填就可以了.找可 ...
- [NOI2017]蔬菜
[NOI2017]蔬菜 题目描述 大意就是有\(n\)种物品,第\(i\)个物品有\(c_i\)个,单价是\(a_i\).然后每天你可以卖出最多\(m\)个物品.每天结束后第\(i\)种物品会减少\( ...
- BZOJ4946[Noi2017]蔬菜——线段树+堆+模拟费用流
题目链接: [Noi2017]蔬菜 题目大意:有$n$种蔬菜,每种蔬菜有$c_{i}$个,每种蔬菜每天有$x_{i}$个单位会坏掉(准确来说每天每种蔬菜坏掉的量是$x_{i}-$当天这种蔬菜卖出量), ...
- 4946: [Noi2017]蔬菜
4946: [Noi2017]蔬菜 http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf 分析: 贪心. 首先可以将一个蔬菜拆成两个,一个是有加成 ...
随机推荐
- Linux命令应用大词典-第35章 终端
35.1 tty:显示当前连接到当前标准输入的终端设备文件名 35.2 consoletype:显示连接到标准输入的控制台类型 35.3 fgconsole:显示活动的虚拟终端数量 35.4 ming ...
- eclipse格式化
一.eclipse格式化的必要性 1.便于阅读 2.便于协作 二.eclipse格式化快捷键 ctrl shift + F
- 1. 两数之和【Leetcode中国,by java】
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用. 示例: 给定 nums = [2, 7, 11, 15], target ...
- git branch 分支与合并
在使用 git 进行分支开发与合并的时候需要用到这些命令.其他基本 git 命令参考 Git 简易食用指南 git branch 查看分支 git branch 查看当前分支情况 创建分支 git b ...
- 十面阿里,七面头条,六个Offer,春招结束
作者:jkgeekjack链接:https://www.nowcoder.com/discuss/80156?type=0&order=0&pos=13&page=2来源:牛客 ...
- POJ 2187 Beauty Contest(凸包+旋转卡壳)
Description Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, ea ...
- 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 ...
- iOS开发实现UIView随着子控件的高度的变化而变化
例子 其实看完上面的叙述,你会思考,到底什么情况下,一个UIView需要只设置坐标不设置大小呢?其实这种场景相当普遍.比如,我们常常会碰到,一个View中有两个Label,两个Label的高度均和内容 ...
- 安装配置erlang_db_driver
erlang-db-driver是北京融易通公司开源的一个erlang支持众多数据库的一个驱动类库,据其wiki介绍,其支持MySQL, Oracle, Sybase, DB2 and Informi ...
- sublime Text3 如何自动排版代码
安装 html beautiful 然后按ctrl+shift+alt+f