[APIO2012]派遣

[APIO2012]派遣

题目大意:

给定一棵\(n(n\le10^5)\)个结点的有根树,每个点有代价\(c_i\)和权值\(l_i\),要求你选定一个结点\(k\),并在对应的子树中选取一个点集\(S\)(不需要包括\(k\))。在满足\(\sum_{i\in S}c_i\le m\)的情况下,最大化\(|S|\cdot l_k\)

思路:

贪心+堆合并。

源代码:

#include<cstdio>
#include<cctype>
#include<ext/pb_ds/priority_queue.hpp>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
typedef long long int64;
const int N=1e5+1;
int par[N],c[N],l[N],sum[N];
__gnu_pbds::priority_queue<int> q[N];
int main() {
	const int n=getint(),m=getint();
	for(register int i=1;i<=n;i++) {
		par[i]=getint();
		sum[i]=c[i]=getint();
		l[i]=getint();
		q[i].push(c[i]);
	}
	int64 ans=0;
	for(register int i=n;i>=1;i--) {
		ans=std::max(ans,l[i]*(int64)q[i].size());
		sum[par[i]]+=sum[i];
		q[par[i]].join(q[i]);
		while(sum[par[i]]>m) {
			sum[par[i]]-=q[par[i]].top();
			q[par[i]].pop();
		}
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-11-23 19:25  skylee03  阅读(132)  评论(0编辑  收藏  举报