• 题解 洛谷 P1552 【[APIO2012]派遣】


    根据题意,我们不难发现忍者之间的关系是树形结构。

    发现答案的统计只是在该节点的子树中,因此我们考虑通过树形(DP)来解决问题。

    从叶子节点开始,从下往上考虑,因为一个节点的最优答案只与他的领导力和在子树中选了几个点有关,与选哪些点无关,所以我们要最大化选点的个数。

    贪心策略即为尽可能的多选点,当选出的点的薪水超过预算时,删去当前选出的点中薪水最大的点,通过这样的策略来保证我们能选出最多的点。

    通过可并堆(左偏树)来实现,同时维护一些信息,选出点的薪水总和(sum),选出点的个数(siz)

    其他的一些细节就看代码吧,统计答案记得开(long long)

    (code:)

    #include<bits/stdc++.h>
    #define maxn 200010
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    ll n,m,root,ans;
    ll fa[maxn],ls[maxn],rs[maxn],dis[maxn],val[maxn],l[maxn],sum[maxn],siz[maxn];
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to)
    {
        e[++edge_cnt]=(edge){to,head[from]};
        head[from]=edge_cnt;
    }
    int find(int x)
    {
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    int merge(int x,int y)
    {
        if(x==y) return 0;
        if(!x||!y) return x+y;
        if(val[x]<val[y]) swap(x,y);
        rs[x]=merge(rs[x],y),fa[rs[x]]=x;
        if(dis[ls[x]]<dis[rs[x]]) swap(ls[x],rs[x]);
        if(rs[x]) dis[x]=dis[rs[x]]+1;
        else dis[x]=0;
        return x;
    }
    void del(int x)
    {
        fa[ls[x]]=ls[x],fa[rs[x]]=rs[x];
        fa[x]=merge(ls[x],rs[x]);
    }
    void dfs(int x)
    {
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            dfs(y);
            siz[x]+=siz[y];
            sum[x]+=sum[y];
            merge(find(x),find(y));
        }
        while(sum[x]>m)
        {
            int rootx=find(x);
            siz[x]--;
            sum[x]-=val[rootx];
            del(rootx);
        }
        ans=max(ans,l[x]*siz[x]);
    }
    int main()
    {
        read(n),read(m);
        for(int i=1;i<=n;++i)
        {
            int fath;
            read(fath),read(val[i]),read(l[i]);
            sum[i]=val[i],siz[i]=1,fa[i]=i;
            if(fath) add(fath,i);
            else root=i;
        }
        dfs(root);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    怎样克服 JavaScript 框架疲劳?
    jQuery 简单归纳总结
    锋利的JQuery —— 事件和动画
    锋利的JQuery —— DOM操作
    锋利的JQuery —— 选择器
    Maven日常 —— 你应该知道的一二三
    《时间简史》—— 读后总结
    Elasticsearch之_default_—— 为索引添加默认映射
    Elasticsearch 动态映射——自动检测
    安装了Node.js 从VScode 使用node -v 和 npm -v等命令却无效
  • 原文地址:https://www.cnblogs.com/lhm-/p/12229824.html
Copyright © 2020-2023  润新知