Java教程

[NOI2017] 蔬菜

本文主要是介绍[NOI2017] 蔬菜,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

前不久做了一道同样出处的题,然后发现这道也做了,居然还是黑题(很好写,但思路我想不到),就花了20分钟回顾了一下

  • 题意:有n种蔬菜,每种都有,\(a_i,s_i,c_i,d_i\)分别表示卖出去一单位的价钱,第一次卖额外得的价钱,初始有多少单位,每天结束时腐烂的单位(最后一天腐烂\(c_i\)%\(d_i\))Q个询问问你\(p_i\)天结束时可得的最大收益
  • 思路:贪心(堆)+并查集
    两个策略:1.菜要尽量再快腐烂完时卖掉。2.优先卖贵的
    用堆满足2,然后记录day[]每天剩余的空间,并查集方便快速找到i天前第一个day[]<m(没满)的一天,然后在这天卖,接着维护信息。
    感性理解:相当于把卖菜方案尽量往后推,先推贵的。不过最后up=1e6>个菜卖完以后,就把所有的往前推,占满前缀连续的格子(当然这个不是操作,是原理,只需要查询[前\(p_i\)*\(m\)个的销售额即可])。
    复杂度\(O(nmlogn)\)
  • code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int n,m,k,c[N],d[N],day[N],fa[N];
ll a[N],s[N],ans[N];
int g_fa(int u) {return fa[u]=(fa[u]==u)?u:g_fa(fa[u]);}
struct node {
	int x;ll w;
	bool operator<(const node &u) const{return w<u.w;}
};
priority_queue<node> Q;
int main() {
//	freopen("mm.in","r",stdin);
//	freopen("mm.out","w",stdout);
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++) scanf("%d%d%d%d",&a[i],&s[i],&c[i],&d[i]);
	for(int i=1;i<=n;i++) Q.push((node){i,s[i]+a[i]});
	for(int i=0;i<=1e6;i++)fa[i]=i;
	int cc=0;
	while(!Q.empty()) {
		int u=Q.top().x;ll w=Q.top().w; Q.pop();
		int dmx=1e6;
		if(d[u]) dmx=min(dmx,(c[u]+d[u]-1)/d[u]);
		dmx=g_fa(dmx);
		if(!dmx) continue;
		day[dmx]++;if(day[dmx]==m)fa[dmx]=g_fa(dmx-1);
		c[u]--;if(c[u])Q.push((node){u,a[u]});
		ans[cc+1]=ans[cc]+w;cc++;
	}
//	printf("%d\n",cc);
	for(int i=1;i<=k;i++) {
		int p; scanf("%d",&p);
		printf("%lld\n",ans[min(cc,p*m)]);
	} 
	return 0;
}
这篇关于[NOI2017] 蔬菜的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!