[bzoj3936][Noi2017]蔬菜【贪心】
【题目描述】
http://www.lydsy.com/JudgeOnline/upload/Noi2017D2.pdf
【题解】
这道题可以从后往前贪心。
若我们知道了第i的答案,我们只要去掉(当前个数-前i-1天能取的个数)个价值最小的蔬菜,就能得到第i-1天的答案。
所以我们现在只要求出最后一天的答案。
把每种蔬菜拆成两份,前c-1个价值为a,最后一个价值为a+s(按变质的顺序)放入优先队列中,依次取出来放入还能放的地方即可。
还能放的地方可以用并查集维护。
复杂度O(n log n)。
/* -------------- user Vanisher problem bzoj-4946 ----------------*/ # include <bits/stdc++.h> # define ll long long # define N 1000100 using namespace std; ll read(){ ll tmp=0, fh=1; char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();} while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();} return tmp*fh; } struct node{ ll num,w,d; }; bool operator <(node x, node y){ return x.w<y.w; } priority_queue <node,vector<node> > hp; ll n,m,k,p[N],mp[N],mx,f[N],num[N],cnt,ans[N]; ll dad(ll x){ if (x>100000) return dad(100000); if (f[x]==x) return x; else return f[x]=dad(f[x]); } int main(){ n=read(), m=read(), k=read(); for (ll i=1; i<=n; i++){ ll a=read(), s=read(), c=read(), x=read(),ti; if (x!=0){ ti=(c-1)/x+1; hp.push((node){1,s+a,-ti}); hp.push((node){c-1,a,x}); } else { hp.push((node){1,s+a,-100000}); hp.push((node){c-1,a,0}); } } mx=100000; for (ll i=1; i<=k; i++) p[i]=read(),mx=max(p[i],mx); for (ll i=1; i<=mx; i++) f[i]=i, num[i]=m; while (hp.size()!=0){ node now=hp.top(); hp.pop(); if (now.d<0){ ll p=dad(-now.d); if (p==0) continue; num[p]--; mp[++cnt]=now.w; if (num[p]==0) f[p]=dad(f[p-1]); ans[mx]=ans[mx]+now.w; } else { ll p,nownum,newp; if (now.d!=0) p=(now.num-1)/now.d+1,nownum=(now.num-1)%now.d+1; else p=100000, nownum=now.num; newp=dad(p), nownum=nownum+(p-newp)*now.d; p=newp; while (p>0){ if (nownum==0&&now.d==0) break; ll del=min(num[p],nownum); for (ll i=1; i<=del; i++) mp[++cnt]=now.w, ans[mx]=ans[mx]+now.w; nownum=nownum-del; num[p]=num[p]-del; if (num[p]==0) f[p]=dad(p-1); newp=dad(f[p-1]); nownum=nownum+(p-newp)*now.d; p=newp; } } } sort(mp+1,mp+cnt+1); ll tot=mx*m,now=ans[mx],l=1; for (ll i=mx-1; i>=1; i--){ tot=tot-m; while (cnt-l+1>tot) now=now-mp[l++]; ans[i]=now; } for (ll i=1; i<=k; i++) printf("%lld\n",ans[p[i]]); return 0; }