[Explanations] NOI2017 vegetables (greedy)
Consider this fact:
If you sell a lot of vegetables in a very long time, but only \ (p \) day you sell food. So in fact, you (p \) \ can also perform the same operation days.
This is because
- Income food does not change with time
- The difference between the volume of the dish does not exist
Title disappear daily fixed \ (x_i \) limit for each vegetable vegetables can be seen as a time to disappear, only to disappear every day \ (m \) vegetables, then we sell the first time after the disappearance of vegetables by. The question then becomes simple. Now it is given a \ (the p-\) , seeking the biggest \ (j \ le p \) so that \ (j \) as well as capacity, is disjoint-set.
Click here to check and analyze the complexity of the set (compression path), the number of times the query set \ (Q \) , complexity \ (O (m * Q + 1E5) \) . (As a point of access will only be m times)
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; typedef long long ll;
inline int qr(){
int ret=0,f=0,c=getchar();
while(!isdigit(c)) f|=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=1e6+5;
int n,m,k;
int a[maxn],s[maxn],c[maxn],x[maxn],r[maxn],sav[maxn],cnt;
ll ans[maxn];
int Find(int x){return x==r[x]?x:r[x]=Find(r[x]);}
priority_queue< pair<int,int> > q;
int main(){
n=qr(),m=qr(),k=qr();
for(int t=1;t<=n;++t)
a[t]=qr(),s[t]=qr(),c[t]=qr(),x[t]=qr(),q.push((pair<int,int>){a[t]+s[t],t});
for(int t=1;t<=1e5;++t) r[t]=t,sav[t]=m;
while(q.size()){
pair<int,int> now=q.top(); q.pop();
int tar=0;
if(x[now.second]) tar=Find(min(100000,(c[now.second]-1)/x[now.second]+1));
else tar=Find(100000);
if(!tar) continue;
--c[now.second]; ans[cnt+1]=ans[cnt]+now.first; ++cnt; --sav[tar];
if(!sav[tar]) r[Find(tar)]=Find(tar-1);
if(c[now.second]) q.push((pair<int,int>){a[now.second],now.second});
}
while(k--) cout<<ans[min(cnt,m*qr())]<<endl;
return 0;
}