[APIO2012]派遣
题目大意:
给定一棵(n(nle10^5))个结点的有根树,每个点有代价(c_i)和权值(l_i),要求你选定一个结点(k),并在对应的子树中选取一个点集(S)(不需要包括(k))。在满足(sum_{iin S}c_ile 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
",ans);
return 0;
}