[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;
}

转载于:https://www.cnblogs.com/skylee03/p/10009369.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值