题目链接

题解:

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

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

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

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

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

时光倒流?

也许可以?

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

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

那么,面对最后一天,我们就剩下这么多的菜了。肯定要卖最贵的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
*/
05-13 06:12