[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 分析: 贪心. 首先可以将一个蔬菜拆成两个,一个是有加成 ...
随机推荐
- Qml-Dialog不能隐藏标题栏和按钮自定义
在项目中,需要弹出一个对话框来完成用户输入的功能,为了考虑界面的同一,这里需要将原生自带的标题栏隐藏掉,换成自己写的 按照widget的写法,可以使用QDialog,但是qml与之对应的Dialog我 ...
- Git 与 GitHub
Git 这个年代,不会点Git真不行啦,少年别问问什么,在公司你就知道了~ Git是一个协同开发的工具,主要作用是进行版本控制,而且还能自动检测代码是否发生变化. 一. 安装 下载地址:https:/ ...
- flume-kafka-storm-hdfs-hadoop-hbase
# bigdata-demo 项目地址: https://github.com/windwant/bigdata-demo.git hadoop: hadoop hdfs操作 log输出到flume ...
- 博客美化—添加萌萌的live2D看板娘(不能再简单了)
看着很多博客都有live2D的萌萌哒看板娘,我闲着有空说干就干. 从参考博客的附件中下载资源文件 waifu.css waifu-tips.js live2d.js flat-ui.min.css// ...
- 手机端网页返回顶部js代码
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" cont ...
- linux NULL 的定义
#undef NULL #if defined(__cplusplus) #define NULL 0 #else #define NULL ((void *)0) #endif
- 贵州省未来二十年的投资机会的探讨1>
贵州的股市 1.000540.SZ 中天金融 2.000589.SZ 黔轮胎A 3.000733.SZ 振华科技 4.000851.SZ 高鸿股份 5.000920.SZ 南方汇通 6.002025. ...
- Struts2中Action各种转发类型
Struts2:Action中result的各种转发类型: 内部请求转发dispatcher(默认值) redirect.redirectAction.plainText1.redirect是重定向到 ...
- es6从零学习(一)let 和 const 命令
es6从零学习(一):let 和 const 命令 一:let 变量 1.块级作用域{}:let只在自己的块级作用域内有效. for(let i =0;i<3;i++) { console.lo ...
- Python中的eval
Python中的eval方法接受一个字符串参数,并且把字符串里面的内容当成Python代码来执行: eval的缺点是执行速度慢,并且会有安全风险