首先我们有一个费用流的做法。
因为保质期这个东西不太好限制,我们把每种蔬菜都按照过期时间分成若干类,每类大概x个,这样就相当于我们有了n*p种蔬菜。每种蔬菜在指定时间过期。我们把S的奖励放到每一种蔬菜过期时间最晚的那一类中去。
我们可以建图,S向每一天i连边,容量为m,费用为0,每一天i向所有第i天过期的蔬菜连边,容量为inf,费用为a,每一天i向下一天i+1连边,容量为inf,费用为0(我把这个作用的边连在了蔬菜那边qaq),每种蔬菜向T连边,容量为个数,费用为0,特别的针对每一种蔬菜的最后一类,我们分出1的流量来建费用为s的边。
这样点数是 O(np+p), O ( n p + p ) , 边数是 O(np+n+p) O ( n p + n + p ) 的。一天一天的增广费用流,可以跑过前60分。
然后性质1,2直接贪心可以再搞16分。
我们考虑此题正解。
我们发现对于p=i时,我们选择的蔬菜,一定是p=i+1时选择的蔬菜的子集。
自己yy一下为什么…大概就是反证肯定不优。
这样的话我们跑费用流时,每次新增一个点后其实不会有退流的操作!
因此我们可以贪心的来模拟这个费用流的增广过程,并用数据结构加速。
注意到增广到第p天时,此时的流合法就是要求对于任意的i,前i天过期的蔬菜卖出的不能超过min(i,p)*m个。
我们记f[i]表示前i天过期的蔬菜卖出的个数,那么我们就是要求 max{f[i]−i∗m}<=0 max { f [ i ] − i ∗ m } <= 0
我们用线段树维护这个东西,并用优先队列按价值从大到小维护当前可用蔬菜,每次贪心的取出前m棵蔬菜,看能否选择这种蔬菜(我们贪心的取最晚过期的那棵蔬菜来更新上面的不等式,如果不合法了,就撤销这次操作,并且这种蔬菜以后再不可能被选中)。
复杂度 O(nlogn+qm(log n+log q)) O ( n l o g n + q m ( l o g n + l o g q ) )
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define pi pair
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,m,K;ll ans[N],nn=100000;
struct Icefox{
int a,s,c,x;
}qq[N];
priority_queuevector,less >q;
struct node{
int mx,tag;
}tr[N<<2];
inline void pushup(int p){
tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
}
inline void doadd(int p,int val){
tr[p].mx+=val;tr[p].tag+=val;
}
inline void pushdown(int p){
if(!tr[p].tag) return;
doadd(p<<1,tr[p].tag);doadd(p<<1|1,tr[p].tag);tr[p].tag=0;
}
inline void build(int p,int l,int r){
if(l==r){tr[p].mx=-l*m;return;}
int mid=l+r>>1;build(p<<1,l,mid);build(p<<1|1,mid+1,r);pushup(p);
}
inline void add(int p,int l,int r,int x,int y,int val){
if(x<=l&&r<=y){doadd(p,val);return;}
int mid=l+r>>1;pushdown(p);
if(x<=mid) add(p<<1,l,mid,x,y,val);
if(y>mid) add(p<<1|1,mid+1,r,x,y,val);pushup(p);
}
inline bool jud(int id){
int t=qq[id].x?(qq[id].c-1)/qq[id].x+1:nn;
add(1,1,nn,t,nn,1);if(tr[1].mx<=0) return 1;
add(1,1,nn,t,nn,-1);return 0;
}
int main(){
// freopen("vegetables3.in","r",stdin);
// freopen("a.out","w",stdout);
n=read();m=read();K=read();
for(int i=1;i<=n;++i){
qq[i].a=read();qq[i].s=read();qq[i].c=read();qq[i].x=read();
q.push(make_pair(qq[i].a+qq[i].s,i));
}ll res=0;build(1,1,nn);
for(int i=1;i<=nn;++i){
int tmp=m;
while(tmp&&!q.empty()){
int x=q.top().first,id=q.top().second;q.pop();
if(!jud(id)) continue;res+=x;--tmp;qq[id].c--;
if(qq[id].c) q.push(make_pair(qq[id].a,id));
}ans[i]=res;
}while(K--) printf("%lld\n",ans[read()]);
return 0;
}
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define pi pair
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,m,K;ll ans[N];
struct Icefox{
int a,s,c,x;
}qq[N];
struct quer{
int x,id;
friend bool operator<(quer a,quer b){return a.xnamespace sol1{
inline bool cmp(Icefox a,Icefox b){return a.a>b.a;}
inline void gao(){
sort(qq+1,qq+n+1,cmp);int now=1;ll res=0;
for(int i=1;i<=K;++i){
int tmp=(qu[i].x-qu[i-1].x)*m;
while(tmp&&now<=n){
if(qq[now].c>=tmp){qq[now].c-=tmp;res+=(ll)tmp*qq[now].a;if(!qq[now].c) ++now;break;}
tmp-=qq[now].c;res+=(ll)qq[now].c*qq[now].a;++now;
}ans[qu[i].id]=res;
}for(int i=1;i<=K;++i) printf("%lld\n",ans[i]);
}
}
namespace sol3{
int h[1002010],num=1,id[1010][1010],tot=0,T,path[1002010];ll dis[1002010];
bool inq[1002010];
struct edge{
int to,next,w,c;
}data[7000010];
inline void add(int x,int y,int w,int c){
data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].w=w;data[num].c=c;
data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].w=0;data[num].c=-c;
}inline bool spfa(){
deque<int>q;memset(dis,-inf,sizeof(dis));memset(path,0,sizeof(path));
q.push_back(0);dis[0]=0;
while(!q.empty()){
int x=q.front();q.pop_front();inq[x]=0;
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;if(!data[i].w) continue;
if(data[i].c+dis[x]>dis[y]){
dis[y]=dis[x]+data[i].c;path[y]=i;
if(!inq[y]){
if(!q.empty()&&dis[q.front()]else q.push_back(y);inq[y]=1;
}
}
}
}return path[T];
}
inline void gao(){
T=++tot;
for(int i=1;i<=n;++i){
for(int j=1;jif(j!=1) add(id[i][j-1],id[i][j],inf,0);
if(qq[i].c<=qq[i].x){add(tot,T,qq[i].c-1,0);qq[i].c=0;break;}
qq[i].c-=qq[i].x;add(id[i][j],T,qq[i].x,0);
}if(qq[i].c){
int j=qu[K].x;id[i][j]=++tot;if(j!=1) add(id[i][j-1],id[i][j],inf,0);
add(tot,T,qq[i].c-1,0);qq[i].c=0;
}add(tot,T,1,qq[i].s);
}int now=1;ll res=0;
for(int i=1;i<=K;++i){
while(now<=qu[i].x){
add(0,++tot,m,0);
for(int j=1;j<=n;++j)
if(id[j][now]) add(tot,id[j][now],inf,qq[j].a);++now;
}while(spfa()){
int cur=T,low=inf;
while(path[cur]) low=min(low,data[path[cur]].w),cur=data[path[cur]^1].to;
res+=(ll)low*dis[T];cur=T;
while(path[cur]) data[path[cur]].w-=low,data[path[cur]^1].w+=low,cur=data[path[cur]^1].to;
}ans[qu[i].id]=res;
}for(int i=1;i<=K;++i) printf("%lld\n",ans[i]);
}
}
namespace sol2{
pi a[N<<1];
inline bool cmp(pi a,pi b){return a.first>b.first;}
inline void gao(){
int tot=0;
for(int i=1;i<=n;++i){
a[++tot]=make_pair(qq[i].a+qq[i].s,1);
if(qq[i].c-1) a[++tot]=make_pair(qq[i].a,qq[i].c-1);
}sort(a+1,a+tot+1,cmp);ll res=0;int now=1;
for(int i=1;i<=K;++i){
int tmp=(qu[i].x-qu[i-1].x)*m;
while(tmp&&now<=tot){
if(a[now].second>=tmp){a[now].second-=tmp;res+=(ll)tmp*a[now].first;if(!a[now].second) ++now;break;}
tmp-=a[now].second;res+=(ll)a[now].second*a[now].first;++now;
}ans[qu[i].id]=res;
}for(int i=1;i<=K;++i) printf("%lld\n",ans[i]);
}
}
int main(){
freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
n=read();m=read();K=read();bool fl1=1,fl2=1;
for(int i=1;i<=n;++i){
qq[i].a=read();qq[i].s=read();qq[i].c=read();qq[i].x=read();
if(qq[i].x) fl1=0;if(qq[i].s) fl2=0;
}for(int i=1;i<=K;++i) qu[i].id=i,qu[i].x=read();sort(qu+1,qu+K+1);
if(fl1&&fl2) sol1::gao();
else if(fl1) sol2::gao();
else sol3::gao();
return 0;
}